abci: Application should return errors errors and nilable response objects (#8396)

This commit is contained in:
Sam Kleinman
2022-04-22 20:40:42 -04:00
committed by GitHub
parent 8345dc4f7c
commit b5e6cf50d1
40 changed files with 717 additions and 670 deletions
+14 -28
View File
@@ -44,71 +44,57 @@ func (app *localClient) Echo(_ context.Context, msg string) (*types.ResponseEcho
}
func (app *localClient) Info(ctx context.Context, req types.RequestInfo) (*types.ResponseInfo, error) {
res := app.Application.Info(ctx, req)
return &res, nil
return app.Application.Info(ctx, req)
}
func (app *localClient) CheckTx(ctx context.Context, req types.RequestCheckTx) (*types.ResponseCheckTx, error) {
res := app.Application.CheckTx(ctx, req)
return &res, nil
return app.Application.CheckTx(ctx, req)
}
func (app *localClient) Query(ctx context.Context, req types.RequestQuery) (*types.ResponseQuery, error) {
res := app.Application.Query(ctx, req)
return &res, nil
return app.Application.Query(ctx, req)
}
func (app *localClient) Commit(ctx context.Context) (*types.ResponseCommit, error) {
res := app.Application.Commit(ctx)
return &res, nil
return app.Application.Commit(ctx)
}
func (app *localClient) InitChain(ctx context.Context, req types.RequestInitChain) (*types.ResponseInitChain, error) {
res := app.Application.InitChain(ctx, req)
return &res, nil
return app.Application.InitChain(ctx, req)
}
func (app *localClient) ListSnapshots(ctx context.Context, req types.RequestListSnapshots) (*types.ResponseListSnapshots, error) {
res := app.Application.ListSnapshots(ctx, req)
return &res, nil
return app.Application.ListSnapshots(ctx, req)
}
func (app *localClient) OfferSnapshot(ctx context.Context, req types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error) {
res := app.Application.OfferSnapshot(ctx, req)
return &res, nil
return app.Application.OfferSnapshot(ctx, req)
}
func (app *localClient) LoadSnapshotChunk(ctx context.Context, req types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) {
res := app.Application.LoadSnapshotChunk(ctx, req)
return &res, nil
return app.Application.LoadSnapshotChunk(ctx, req)
}
func (app *localClient) ApplySnapshotChunk(ctx context.Context, req types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) {
res := app.Application.ApplySnapshotChunk(ctx, req)
return &res, nil
return app.Application.ApplySnapshotChunk(ctx, req)
}
func (app *localClient) PrepareProposal(ctx context.Context, req types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) {
res := app.Application.PrepareProposal(ctx, req)
return &res, nil
return app.Application.PrepareProposal(ctx, req)
}
func (app *localClient) ProcessProposal(ctx context.Context, req types.RequestProcessProposal) (*types.ResponseProcessProposal, error) {
res := app.Application.ProcessProposal(ctx, req)
return &res, nil
return app.Application.ProcessProposal(ctx, req)
}
func (app *localClient) ExtendVote(ctx context.Context, req types.RequestExtendVote) (*types.ResponseExtendVote, error) {
res := app.Application.ExtendVote(ctx, req)
return &res, nil
return app.Application.ExtendVote(ctx, req)
}
func (app *localClient) VerifyVoteExtension(ctx context.Context, req types.RequestVerifyVoteExtension) (*types.ResponseVerifyVoteExtension, error) {
res := app.Application.VerifyVoteExtension(ctx, req)
return &res, nil
return app.Application.VerifyVoteExtension(ctx, req)
}
func (app *localClient) FinalizeBlock(ctx context.Context, req types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error) {
res := app.Application.FinalizeBlock(ctx, req)
return &res, nil
return app.Application.FinalizeBlock(ctx, req)
}
+2 -1
View File
@@ -422,9 +422,10 @@ func (_m *Client) Wait() {
_m.Called()
}
// NewClient creates a new instance of Client. It also registers a cleanup function to assert the mocks expectations.
// NewClient creates a new instance of Client. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
func NewClient(t testing.TB) *Client {
mock := &Client{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
+3 -2
View File
@@ -33,8 +33,9 @@ func RandVals(cnt int) []types.ValidatorUpdate {
// InitKVStore initializes the kvstore app with some data,
// which allows tests to pass and is fine as long as you
// don't make any tx that modify the validator state
func InitKVStore(ctx context.Context, app *PersistentKVStoreApplication) {
app.InitChain(ctx, types.RequestInitChain{
func InitKVStore(ctx context.Context, app *PersistentKVStoreApplication) error {
_, err := app.InitChain(ctx, types.RequestInitChain{
Validators: RandVals(1),
})
return err
}
+23 -23
View File
@@ -91,7 +91,7 @@ func NewApplication() *Application {
}
}
func (app *Application) InitChain(_ context.Context, req types.RequestInitChain) types.ResponseInitChain {
func (app *Application) InitChain(_ context.Context, req types.RequestInitChain) (*types.ResponseInitChain, error) {
app.mu.Lock()
defer app.mu.Unlock()
@@ -102,19 +102,19 @@ func (app *Application) InitChain(_ context.Context, req types.RequestInitChain)
panic("problem updating validators")
}
}
return types.ResponseInitChain{}
return &types.ResponseInitChain{}, nil
}
func (app *Application) Info(_ context.Context, req types.RequestInfo) types.ResponseInfo {
func (app *Application) Info(_ context.Context, req types.RequestInfo) (*types.ResponseInfo, error) {
app.mu.Lock()
defer app.mu.Unlock()
return types.ResponseInfo{
return &types.ResponseInfo{
Data: fmt.Sprintf("{\"size\":%v}", app.state.Size),
Version: version.ABCIVersion,
AppVersion: ProtocolVersion,
LastBlockHeight: app.state.Height,
LastBlockAppHash: app.state.AppHash,
}
}, nil
}
// tx is either "val:pubkey!power" or "key=value" or just arbitrary bytes
@@ -167,7 +167,7 @@ func (app *Application) Close() error {
return app.state.db.Close()
}
func (app *Application) FinalizeBlock(_ context.Context, req types.RequestFinalizeBlock) types.ResponseFinalizeBlock {
func (app *Application) FinalizeBlock(_ context.Context, req types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error) {
app.mu.Lock()
defer app.mu.Unlock()
@@ -196,14 +196,14 @@ func (app *Application) FinalizeBlock(_ context.Context, req types.RequestFinali
respTxs[i] = app.handleTx(tx)
}
return types.ResponseFinalizeBlock{TxResults: respTxs, ValidatorUpdates: app.ValUpdates}
return &types.ResponseFinalizeBlock{TxResults: respTxs, ValidatorUpdates: app.ValUpdates}, nil
}
func (*Application) CheckTx(_ context.Context, req types.RequestCheckTx) types.ResponseCheckTx {
return types.ResponseCheckTx{Code: code.CodeTypeOK, GasWanted: 1}
func (*Application) CheckTx(_ context.Context, req types.RequestCheckTx) (*types.ResponseCheckTx, error) {
return &types.ResponseCheckTx{Code: code.CodeTypeOK, GasWanted: 1}, nil
}
func (app *Application) Commit(_ context.Context) types.ResponseCommit {
func (app *Application) Commit(_ context.Context) (*types.ResponseCommit, error) {
app.mu.Lock()
defer app.mu.Unlock()
@@ -214,15 +214,15 @@ func (app *Application) Commit(_ context.Context) types.ResponseCommit {
app.state.Height++
saveState(app.state)
resp := types.ResponseCommit{Data: appHash}
resp := &types.ResponseCommit{Data: appHash}
if app.RetainBlocks > 0 && app.state.Height >= app.RetainBlocks {
resp.RetainHeight = app.state.Height - app.RetainBlocks + 1
}
return resp
return resp, nil
}
// Returns an associated value or nil if missing.
func (app *Application) Query(_ context.Context, reqQuery types.RequestQuery) types.ResponseQuery {
func (app *Application) Query(_ context.Context, reqQuery types.RequestQuery) (*types.ResponseQuery, error) {
app.mu.Lock()
defer app.mu.Unlock()
@@ -233,10 +233,10 @@ func (app *Application) Query(_ context.Context, reqQuery types.RequestQuery) ty
panic(err)
}
return types.ResponseQuery{
return &types.ResponseQuery{
Key: reqQuery.Data,
Value: value,
}
}, nil
}
if reqQuery.Prove {
@@ -258,7 +258,7 @@ func (app *Application) Query(_ context.Context, reqQuery types.RequestQuery) ty
resQuery.Log = "exists"
}
return resQuery
return &resQuery, nil
}
value, err := app.state.db.Get(prefixKey(reqQuery.Data))
@@ -278,25 +278,25 @@ func (app *Application) Query(_ context.Context, reqQuery types.RequestQuery) ty
resQuery.Log = "exists"
}
return resQuery
return &resQuery, nil
}
func (app *Application) PrepareProposal(_ context.Context, req types.RequestPrepareProposal) types.ResponsePrepareProposal {
func (app *Application) PrepareProposal(_ context.Context, req types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) {
app.mu.Lock()
defer app.mu.Unlock()
return types.ResponsePrepareProposal{
return &types.ResponsePrepareProposal{
TxRecords: app.substPrepareTx(req.Txs, req.MaxTxBytes),
}
}, nil
}
func (*Application) ProcessProposal(_ context.Context, req types.RequestProcessProposal) types.ResponseProcessProposal {
func (*Application) ProcessProposal(_ context.Context, req types.RequestProcessProposal) (*types.ResponseProcessProposal, error) {
for _, tx := range req.Txs {
if len(tx) == 0 {
return types.ResponseProcessProposal{Status: types.ResponseProcessProposal_REJECT}
return &types.ResponseProcessProposal{Status: types.ResponseProcessProposal_REJECT}, nil
}
}
return types.ResponseProcessProposal{Status: types.ResponseProcessProposal_ACCEPT}
return &types.ResponseProcessProposal{Status: types.ResponseProcessProposal_ACCEPT}, nil
}
//---------------------------------------------
+44 -14
View File
@@ -25,35 +25,41 @@ const (
func testKVStore(ctx context.Context, t *testing.T, app types.Application, tx []byte, key, value string) {
req := types.RequestFinalizeBlock{Txs: [][]byte{tx}}
ar := app.FinalizeBlock(ctx, req)
ar, err := app.FinalizeBlock(ctx, req)
require.NoError(t, err)
require.Equal(t, 1, len(ar.TxResults))
require.False(t, ar.TxResults[0].IsErr())
// repeating tx doesn't raise error
ar = app.FinalizeBlock(ctx, req)
ar, err = app.FinalizeBlock(ctx, req)
require.NoError(t, err)
require.Equal(t, 1, len(ar.TxResults))
require.False(t, ar.TxResults[0].IsErr())
// commit
app.Commit(ctx)
_, err = app.Commit(ctx)
require.NoError(t, err)
info := app.Info(ctx, types.RequestInfo{})
info, err := app.Info(ctx, types.RequestInfo{})
require.NoError(t, err)
require.NotZero(t, info.LastBlockHeight)
// make sure query is fine
resQuery := app.Query(ctx, types.RequestQuery{
resQuery, err := app.Query(ctx, types.RequestQuery{
Path: "/store",
Data: []byte(key),
})
require.NoError(t, err)
require.Equal(t, code.CodeTypeOK, resQuery.Code)
require.Equal(t, key, string(resQuery.Key))
require.Equal(t, value, string(resQuery.Value))
require.EqualValues(t, info.LastBlockHeight, resQuery.Height)
// make sure proof is fine
resQuery = app.Query(ctx, types.RequestQuery{
resQuery, err = app.Query(ctx, types.RequestQuery{
Path: "/store",
Data: []byte(key),
Prove: true,
})
require.NoError(t, err)
require.EqualValues(t, code.CodeTypeOK, resQuery.Code)
require.Equal(t, key, string(resQuery.Key))
require.Equal(t, value, string(resQuery.Value))
@@ -100,10 +106,16 @@ func TestPersistentKVStoreInfo(t *testing.T) {
logger := log.NewNopLogger()
kvstore := NewPersistentKVStoreApplication(logger, dir)
InitKVStore(ctx, kvstore)
if err := InitKVStore(ctx, kvstore); err != nil {
t.Fatal(err)
}
height := int64(0)
resInfo := kvstore.Info(ctx, types.RequestInfo{})
resInfo, err := kvstore.Info(ctx, types.RequestInfo{})
if err != nil {
t.Fatal(err)
}
if resInfo.LastBlockHeight != height {
t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight)
}
@@ -111,10 +123,19 @@ func TestPersistentKVStoreInfo(t *testing.T) {
// make and apply block
height = int64(1)
hash := []byte("foo")
kvstore.FinalizeBlock(ctx, types.RequestFinalizeBlock{Hash: hash, Height: height})
kvstore.Commit(ctx)
if _, err := kvstore.FinalizeBlock(ctx, types.RequestFinalizeBlock{Hash: hash, Height: height}); err != nil {
t.Fatal(err)
}
resInfo = kvstore.Info(ctx, types.RequestInfo{})
if _, err := kvstore.Commit(ctx); err != nil {
t.Fatal(err)
}
resInfo, err = kvstore.Info(ctx, types.RequestInfo{})
if err != nil {
t.Fatal(err)
}
if resInfo.LastBlockHeight != height {
t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight)
}
@@ -133,9 +154,12 @@ func TestValUpdates(t *testing.T) {
nInit := 5
vals := RandVals(total)
// initialize with the first nInit
kvstore.InitChain(ctx, types.RequestInitChain{
_, err := kvstore.InitChain(ctx, types.RequestInitChain{
Validators: vals[:nInit],
})
if err != nil {
t.Fatal(err)
}
vals1, vals2 := vals[:nInit], kvstore.Validators()
valsEqual(t, vals1, vals2)
@@ -191,13 +215,19 @@ func makeApplyBlock(ctx context.Context, t *testing.T, kvstore types.Application
// make and apply block
height := int64(heightInt)
hash := []byte("foo")
resFinalizeBlock := kvstore.FinalizeBlock(ctx, types.RequestFinalizeBlock{
resFinalizeBlock, err := kvstore.FinalizeBlock(ctx, types.RequestFinalizeBlock{
Hash: hash,
Height: height,
Txs: txs,
})
if err != nil {
t.Fatal(err)
}
kvstore.Commit(ctx)
_, err = kvstore.Commit(ctx)
if err != nil {
t.Fatal(err)
}
valsEqual(t, diff, resFinalizeBlock.ValidatorUpdates)
+4 -4
View File
@@ -37,10 +37,10 @@ func NewPersistentKVStoreApplication(logger log.Logger, dbDir string) *Persisten
}
}
func (app *PersistentKVStoreApplication) OfferSnapshot(_ context.Context, req types.RequestOfferSnapshot) types.ResponseOfferSnapshot {
return types.ResponseOfferSnapshot{Result: types.ResponseOfferSnapshot_ABORT}
func (app *PersistentKVStoreApplication) OfferSnapshot(_ context.Context, req types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error) {
return &types.ResponseOfferSnapshot{Result: types.ResponseOfferSnapshot_ABORT}, nil
}
func (app *PersistentKVStoreApplication) ApplySnapshotChunk(_ context.Context, req types.RequestApplySnapshotChunk) types.ResponseApplySnapshotChunk {
return types.ResponseApplySnapshotChunk{Result: types.ResponseApplySnapshotChunk_ABORT}
func (app *PersistentKVStoreApplication) ApplySnapshotChunk(_ context.Context, req types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) {
return &types.ResponseApplySnapshotChunk{Result: types.ResponseApplySnapshotChunk_ABORT}, nil
}
+14 -28
View File
@@ -79,71 +79,57 @@ func (app *gRPCApplication) Flush(_ context.Context, req *types.RequestFlush) (*
}
func (app *gRPCApplication) Info(ctx context.Context, req *types.RequestInfo) (*types.ResponseInfo, error) {
res := app.app.Info(ctx, *req)
return &res, nil
return app.app.Info(ctx, *req)
}
func (app *gRPCApplication) CheckTx(ctx context.Context, req *types.RequestCheckTx) (*types.ResponseCheckTx, error) {
res := app.app.CheckTx(ctx, *req)
return &res, nil
return app.app.CheckTx(ctx, *req)
}
func (app *gRPCApplication) Query(ctx context.Context, req *types.RequestQuery) (*types.ResponseQuery, error) {
res := app.app.Query(ctx, *req)
return &res, nil
return app.app.Query(ctx, *req)
}
func (app *gRPCApplication) Commit(ctx context.Context, req *types.RequestCommit) (*types.ResponseCommit, error) {
res := app.app.Commit(ctx)
return &res, nil
return app.app.Commit(ctx)
}
func (app *gRPCApplication) InitChain(ctx context.Context, req *types.RequestInitChain) (*types.ResponseInitChain, error) {
res := app.app.InitChain(ctx, *req)
return &res, nil
return app.app.InitChain(ctx, *req)
}
func (app *gRPCApplication) ListSnapshots(ctx context.Context, req *types.RequestListSnapshots) (*types.ResponseListSnapshots, error) {
res := app.app.ListSnapshots(ctx, *req)
return &res, nil
return app.app.ListSnapshots(ctx, *req)
}
func (app *gRPCApplication) OfferSnapshot(ctx context.Context, req *types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error) {
res := app.app.OfferSnapshot(ctx, *req)
return &res, nil
return app.app.OfferSnapshot(ctx, *req)
}
func (app *gRPCApplication) LoadSnapshotChunk(ctx context.Context, req *types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) {
res := app.app.LoadSnapshotChunk(ctx, *req)
return &res, nil
return app.app.LoadSnapshotChunk(ctx, *req)
}
func (app *gRPCApplication) ApplySnapshotChunk(ctx context.Context, req *types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) {
res := app.app.ApplySnapshotChunk(ctx, *req)
return &res, nil
return app.app.ApplySnapshotChunk(ctx, *req)
}
func (app *gRPCApplication) ExtendVote(ctx context.Context, req *types.RequestExtendVote) (*types.ResponseExtendVote, error) {
res := app.app.ExtendVote(ctx, *req)
return &res, nil
return app.app.ExtendVote(ctx, *req)
}
func (app *gRPCApplication) VerifyVoteExtension(ctx context.Context, req *types.RequestVerifyVoteExtension) (*types.ResponseVerifyVoteExtension, error) {
res := app.app.VerifyVoteExtension(ctx, *req)
return &res, nil
return app.app.VerifyVoteExtension(ctx, *req)
}
func (app *gRPCApplication) PrepareProposal(ctx context.Context, req *types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) {
res := app.app.PrepareProposal(ctx, *req)
return &res, nil
return app.app.PrepareProposal(ctx, *req)
}
func (app *gRPCApplication) ProcessProposal(ctx context.Context, req *types.RequestProcessProposal) (*types.ResponseProcessProposal, error) {
res := app.app.ProcessProposal(ctx, *req)
return &res, nil
return app.app.ProcessProposal(ctx, *req)
}
func (app *gRPCApplication) FinalizeBlock(ctx context.Context, req *types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error) {
res := app.app.FinalizeBlock(ctx, *req)
return &res, nil
return app.app.FinalizeBlock(ctx, *req)
}
+82 -21
View File
@@ -159,8 +159,7 @@ func (s *SocketServer) acceptConnectionsRoutine(ctx context.Context) {
}
// Read requests from conn and deal with them
func (s *SocketServer) handleRequests(ctx context.Context, closer func(error), conn io.Reader, responses chan<- *types.Response,
) {
func (s *SocketServer) handleRequests(ctx context.Context, closer func(error), conn io.Reader, responses chan<- *types.Response) {
var bufReader = bufio.NewReader(conn)
defer func() {
@@ -180,7 +179,12 @@ func (s *SocketServer) handleRequests(ctx context.Context, closer func(error), c
return
}
resp := s.processRequest(ctx, req)
resp, err := s.processRequest(ctx, req)
if err != nil {
closer(err)
return
}
select {
case <-ctx.Done():
closer(ctx.Err())
@@ -190,42 +194,99 @@ func (s *SocketServer) handleRequests(ctx context.Context, closer func(error), c
}
}
func (s *SocketServer) processRequest(ctx context.Context, req *types.Request) *types.Response {
func (s *SocketServer) processRequest(ctx context.Context, req *types.Request) (*types.Response, error) {
switch r := req.Value.(type) {
case *types.Request_Echo:
return types.ToResponseEcho(r.Echo.Message)
return types.ToResponseEcho(r.Echo.Message), nil
case *types.Request_Flush:
return types.ToResponseFlush()
return types.ToResponseFlush(), nil
case *types.Request_Info:
return types.ToResponseInfo(s.app.Info(ctx, *r.Info))
res, err := s.app.Info(ctx, *r.Info)
if err != nil {
return nil, err
}
return types.ToResponseInfo(res), nil
case *types.Request_CheckTx:
return types.ToResponseCheckTx(s.app.CheckTx(ctx, *r.CheckTx))
res, err := s.app.CheckTx(ctx, *r.CheckTx)
if err != nil {
return nil, err
}
return types.ToResponseCheckTx(res), nil
case *types.Request_Commit:
return types.ToResponseCommit(s.app.Commit(ctx))
res, err := s.app.Commit(ctx)
if err != nil {
return nil, err
}
return types.ToResponseCommit(res), nil
case *types.Request_Query:
return types.ToResponseQuery(s.app.Query(ctx, *r.Query))
res, err := s.app.Query(ctx, *r.Query)
if err != nil {
return nil, err
}
return types.ToResponseQuery(res), nil
case *types.Request_InitChain:
return types.ToResponseInitChain(s.app.InitChain(ctx, *r.InitChain))
res, err := s.app.InitChain(ctx, *r.InitChain)
if err != nil {
return nil, err
}
return types.ToResponseInitChain(res), nil
case *types.Request_ListSnapshots:
return types.ToResponseListSnapshots(s.app.ListSnapshots(ctx, *r.ListSnapshots))
res, err := s.app.ListSnapshots(ctx, *r.ListSnapshots)
if err != nil {
return nil, err
}
return types.ToResponseListSnapshots(res), nil
case *types.Request_OfferSnapshot:
return types.ToResponseOfferSnapshot(s.app.OfferSnapshot(ctx, *r.OfferSnapshot))
res, err := s.app.OfferSnapshot(ctx, *r.OfferSnapshot)
if err != nil {
return nil, err
}
return types.ToResponseOfferSnapshot(res), nil
case *types.Request_PrepareProposal:
return types.ToResponsePrepareProposal(s.app.PrepareProposal(ctx, *r.PrepareProposal))
res, err := s.app.PrepareProposal(ctx, *r.PrepareProposal)
if err != nil {
return nil, err
}
return types.ToResponsePrepareProposal(res), nil
case *types.Request_ProcessProposal:
return types.ToResponseProcessProposal(s.app.ProcessProposal(ctx, *r.ProcessProposal))
res, err := s.app.ProcessProposal(ctx, *r.ProcessProposal)
if err != nil {
return nil, err
}
return types.ToResponseProcessProposal(res), nil
case *types.Request_LoadSnapshotChunk:
return types.ToResponseLoadSnapshotChunk(s.app.LoadSnapshotChunk(ctx, *r.LoadSnapshotChunk))
res, err := s.app.LoadSnapshotChunk(ctx, *r.LoadSnapshotChunk)
if err != nil {
return nil, err
}
return types.ToResponseLoadSnapshotChunk(res), nil
case *types.Request_ApplySnapshotChunk:
return types.ToResponseApplySnapshotChunk(s.app.ApplySnapshotChunk(ctx, *r.ApplySnapshotChunk))
res, err := s.app.ApplySnapshotChunk(ctx, *r.ApplySnapshotChunk)
if err != nil {
return nil, err
}
return types.ToResponseApplySnapshotChunk(res), nil
case *types.Request_ExtendVote:
return types.ToResponseExtendVote(s.app.ExtendVote(ctx, *r.ExtendVote))
res, err := s.app.ExtendVote(ctx, *r.ExtendVote)
if err != nil {
return nil, err
}
return types.ToResponseExtendVote(res), nil
case *types.Request_VerifyVoteExtension:
return types.ToResponseVerifyVoteExtension(s.app.VerifyVoteExtension(ctx, *r.VerifyVoteExtension))
res, err := s.app.VerifyVoteExtension(ctx, *r.VerifyVoteExtension)
if err != nil {
return nil, err
}
return types.ToResponseVerifyVoteExtension(res), nil
case *types.Request_FinalizeBlock:
return types.ToResponseFinalizeBlock(s.app.FinalizeBlock(ctx, *r.FinalizeBlock))
res, err := s.app.FinalizeBlock(ctx, *r.FinalizeBlock)
if err != nil {
return nil, err
}
return types.ToResponseFinalizeBlock(res), nil
default:
return types.ToResponseException("Unknown request")
return types.ToResponseException("Unknown request"), errors.New("unknown request type")
}
}
+44 -46
View File
@@ -5,34 +5,32 @@ import "context"
//go:generate ../../scripts/mockery_generate.sh Application
// Application is an interface that enables any finite, deterministic state machine
// to be driven by a blockchain-based replication engine via the ABCI.
// All methods take a RequestXxx argument and return a ResponseXxx argument,
// except CheckTx/DeliverTx, which take `tx []byte`, and `Commit`, which takes nothing.
type Application interface {
// Info/Query Connection
Info(context.Context, RequestInfo) ResponseInfo // Return application info
Query(context.Context, RequestQuery) ResponseQuery // Query for state
Info(context.Context, RequestInfo) (*ResponseInfo, error) // Return application info
Query(context.Context, RequestQuery) (*ResponseQuery, error) // Query for state
// Mempool Connection
CheckTx(context.Context, RequestCheckTx) ResponseCheckTx // Validate a tx for the mempool
CheckTx(context.Context, RequestCheckTx) (*ResponseCheckTx, error) // Validate a tx for the mempool
// Consensus Connection
InitChain(context.Context, RequestInitChain) ResponseInitChain // Initialize blockchain w validators/other info from TendermintCore
PrepareProposal(context.Context, RequestPrepareProposal) ResponsePrepareProposal
ProcessProposal(context.Context, RequestProcessProposal) ResponseProcessProposal
InitChain(context.Context, RequestInitChain) (*ResponseInitChain, error) // Initialize blockchain w validators/other info from TendermintCore
PrepareProposal(context.Context, RequestPrepareProposal) (*ResponsePrepareProposal, error)
ProcessProposal(context.Context, RequestProcessProposal) (*ResponseProcessProposal, error)
// Commit the state and return the application Merkle root hash
Commit(context.Context) ResponseCommit
Commit(context.Context) (*ResponseCommit, error)
// Create application specific vote extension
ExtendVote(context.Context, RequestExtendVote) ResponseExtendVote
ExtendVote(context.Context, RequestExtendVote) (*ResponseExtendVote, error)
// Verify application's vote extension data
VerifyVoteExtension(context.Context, RequestVerifyVoteExtension) ResponseVerifyVoteExtension
VerifyVoteExtension(context.Context, RequestVerifyVoteExtension) (*ResponseVerifyVoteExtension, error)
// Deliver the decided block with its txs to the Application
FinalizeBlock(context.Context, RequestFinalizeBlock) ResponseFinalizeBlock
FinalizeBlock(context.Context, RequestFinalizeBlock) (*ResponseFinalizeBlock, error)
// State Sync Connection
ListSnapshots(context.Context, RequestListSnapshots) ResponseListSnapshots // List available snapshots
OfferSnapshot(context.Context, RequestOfferSnapshot) ResponseOfferSnapshot // Offer a snapshot to the application
LoadSnapshotChunk(context.Context, RequestLoadSnapshotChunk) ResponseLoadSnapshotChunk // Load a snapshot chunk
ApplySnapshotChunk(context.Context, RequestApplySnapshotChunk) ResponseApplySnapshotChunk // Apply a shapshot chunk
ListSnapshots(context.Context, RequestListSnapshots) (*ResponseListSnapshots, error) // List available snapshots
OfferSnapshot(context.Context, RequestOfferSnapshot) (*ResponseOfferSnapshot, error) // Offer a snapshot to the application
LoadSnapshotChunk(context.Context, RequestLoadSnapshotChunk) (*ResponseLoadSnapshotChunk, error) // Load a snapshot chunk
ApplySnapshotChunk(context.Context, RequestApplySnapshotChunk) (*ResponseApplySnapshotChunk, error) // Apply a shapshot chunk
}
//-------------------------------------------------------
@@ -46,53 +44,53 @@ func NewBaseApplication() *BaseApplication {
return &BaseApplication{}
}
func (BaseApplication) Info(_ context.Context, req RequestInfo) ResponseInfo {
return ResponseInfo{}
func (BaseApplication) Info(_ context.Context, req RequestInfo) (*ResponseInfo, error) {
return &ResponseInfo{}, nil
}
func (BaseApplication) CheckTx(_ context.Context, req RequestCheckTx) ResponseCheckTx {
return ResponseCheckTx{Code: CodeTypeOK}
func (BaseApplication) CheckTx(_ context.Context, req RequestCheckTx) (*ResponseCheckTx, error) {
return &ResponseCheckTx{Code: CodeTypeOK}, nil
}
func (BaseApplication) Commit(_ context.Context) ResponseCommit {
return ResponseCommit{}
func (BaseApplication) Commit(_ context.Context) (*ResponseCommit, error) {
return &ResponseCommit{}, nil
}
func (BaseApplication) ExtendVote(_ context.Context, req RequestExtendVote) ResponseExtendVote {
return ResponseExtendVote{}
func (BaseApplication) ExtendVote(_ context.Context, req RequestExtendVote) (*ResponseExtendVote, error) {
return &ResponseExtendVote{}, nil
}
func (BaseApplication) VerifyVoteExtension(_ context.Context, req RequestVerifyVoteExtension) ResponseVerifyVoteExtension {
return ResponseVerifyVoteExtension{
func (BaseApplication) VerifyVoteExtension(_ context.Context, req RequestVerifyVoteExtension) (*ResponseVerifyVoteExtension, error) {
return &ResponseVerifyVoteExtension{
Status: ResponseVerifyVoteExtension_ACCEPT,
}
}, nil
}
func (BaseApplication) Query(_ context.Context, req RequestQuery) ResponseQuery {
return ResponseQuery{Code: CodeTypeOK}
func (BaseApplication) Query(_ context.Context, req RequestQuery) (*ResponseQuery, error) {
return &ResponseQuery{Code: CodeTypeOK}, nil
}
func (BaseApplication) InitChain(_ context.Context, req RequestInitChain) ResponseInitChain {
return ResponseInitChain{}
func (BaseApplication) InitChain(_ context.Context, req RequestInitChain) (*ResponseInitChain, error) {
return &ResponseInitChain{}, nil
}
func (BaseApplication) ListSnapshots(_ context.Context, req RequestListSnapshots) ResponseListSnapshots {
return ResponseListSnapshots{}
func (BaseApplication) ListSnapshots(_ context.Context, req RequestListSnapshots) (*ResponseListSnapshots, error) {
return &ResponseListSnapshots{}, nil
}
func (BaseApplication) OfferSnapshot(_ context.Context, req RequestOfferSnapshot) ResponseOfferSnapshot {
return ResponseOfferSnapshot{}
func (BaseApplication) OfferSnapshot(_ context.Context, req RequestOfferSnapshot) (*ResponseOfferSnapshot, error) {
return &ResponseOfferSnapshot{}, nil
}
func (BaseApplication) LoadSnapshotChunk(_ context.Context, _ RequestLoadSnapshotChunk) ResponseLoadSnapshotChunk {
return ResponseLoadSnapshotChunk{}
func (BaseApplication) LoadSnapshotChunk(_ context.Context, _ RequestLoadSnapshotChunk) (*ResponseLoadSnapshotChunk, error) {
return &ResponseLoadSnapshotChunk{}, nil
}
func (BaseApplication) ApplySnapshotChunk(_ context.Context, req RequestApplySnapshotChunk) ResponseApplySnapshotChunk {
return ResponseApplySnapshotChunk{}
func (BaseApplication) ApplySnapshotChunk(_ context.Context, req RequestApplySnapshotChunk) (*ResponseApplySnapshotChunk, error) {
return &ResponseApplySnapshotChunk{}, nil
}
func (BaseApplication) PrepareProposal(_ context.Context, req RequestPrepareProposal) ResponsePrepareProposal {
func (BaseApplication) PrepareProposal(_ context.Context, req RequestPrepareProposal) (*ResponsePrepareProposal, error) {
trs := make([]*TxRecord, 0, len(req.Txs))
var totalBytes int64
for _, tx := range req.Txs {
@@ -105,19 +103,19 @@ func (BaseApplication) PrepareProposal(_ context.Context, req RequestPrepareProp
Tx: tx,
})
}
return ResponsePrepareProposal{TxRecords: trs}
return &ResponsePrepareProposal{TxRecords: trs}, nil
}
func (BaseApplication) ProcessProposal(_ context.Context, req RequestProcessProposal) ResponseProcessProposal {
return ResponseProcessProposal{Status: ResponseProcessProposal_ACCEPT}
func (BaseApplication) ProcessProposal(_ context.Context, req RequestProcessProposal) (*ResponseProcessProposal, error) {
return &ResponseProcessProposal{Status: ResponseProcessProposal_ACCEPT}, nil
}
func (BaseApplication) FinalizeBlock(_ context.Context, req RequestFinalizeBlock) ResponseFinalizeBlock {
func (BaseApplication) FinalizeBlock(_ context.Context, req RequestFinalizeBlock) (*ResponseFinalizeBlock, error) {
txs := make([]*ExecTxResult, len(req.Txs))
for i := range req.Txs {
txs[i] = &ExecTxResult{Code: CodeTypeOK}
}
return ResponseFinalizeBlock{
return &ResponseFinalizeBlock{
TxResults: txs,
}
}, nil
}
+28 -28
View File
@@ -143,86 +143,86 @@ func ToResponseFlush() *Response {
}
}
func ToResponseInfo(res ResponseInfo) *Response {
func ToResponseInfo(res *ResponseInfo) *Response {
return &Response{
Value: &Response_Info{&res},
Value: &Response_Info{res},
}
}
func ToResponseCheckTx(res ResponseCheckTx) *Response {
func ToResponseCheckTx(res *ResponseCheckTx) *Response {
return &Response{
Value: &Response_CheckTx{&res},
Value: &Response_CheckTx{res},
}
}
func ToResponseCommit(res ResponseCommit) *Response {
func ToResponseCommit(res *ResponseCommit) *Response {
return &Response{
Value: &Response_Commit{&res},
Value: &Response_Commit{res},
}
}
func ToResponseQuery(res ResponseQuery) *Response {
func ToResponseQuery(res *ResponseQuery) *Response {
return &Response{
Value: &Response_Query{&res},
Value: &Response_Query{res},
}
}
func ToResponseInitChain(res ResponseInitChain) *Response {
func ToResponseInitChain(res *ResponseInitChain) *Response {
return &Response{
Value: &Response_InitChain{&res},
Value: &Response_InitChain{res},
}
}
func ToResponseListSnapshots(res ResponseListSnapshots) *Response {
func ToResponseListSnapshots(res *ResponseListSnapshots) *Response {
return &Response{
Value: &Response_ListSnapshots{&res},
Value: &Response_ListSnapshots{res},
}
}
func ToResponseOfferSnapshot(res ResponseOfferSnapshot) *Response {
func ToResponseOfferSnapshot(res *ResponseOfferSnapshot) *Response {
return &Response{
Value: &Response_OfferSnapshot{&res},
Value: &Response_OfferSnapshot{res},
}
}
func ToResponseLoadSnapshotChunk(res ResponseLoadSnapshotChunk) *Response {
func ToResponseLoadSnapshotChunk(res *ResponseLoadSnapshotChunk) *Response {
return &Response{
Value: &Response_LoadSnapshotChunk{&res},
Value: &Response_LoadSnapshotChunk{res},
}
}
func ToResponseApplySnapshotChunk(res ResponseApplySnapshotChunk) *Response {
func ToResponseApplySnapshotChunk(res *ResponseApplySnapshotChunk) *Response {
return &Response{
Value: &Response_ApplySnapshotChunk{&res},
Value: &Response_ApplySnapshotChunk{res},
}
}
func ToResponseExtendVote(res ResponseExtendVote) *Response {
func ToResponseExtendVote(res *ResponseExtendVote) *Response {
return &Response{
Value: &Response_ExtendVote{&res},
Value: &Response_ExtendVote{res},
}
}
func ToResponseVerifyVoteExtension(res ResponseVerifyVoteExtension) *Response {
func ToResponseVerifyVoteExtension(res *ResponseVerifyVoteExtension) *Response {
return &Response{
Value: &Response_VerifyVoteExtension{&res},
Value: &Response_VerifyVoteExtension{res},
}
}
func ToResponsePrepareProposal(res ResponsePrepareProposal) *Response {
func ToResponsePrepareProposal(res *ResponsePrepareProposal) *Response {
return &Response{
Value: &Response_PrepareProposal{&res},
Value: &Response_PrepareProposal{res},
}
}
func ToResponseProcessProposal(res ResponseProcessProposal) *Response {
func ToResponseProcessProposal(res *ResponseProcessProposal) *Response {
return &Response{
Value: &Response_ProcessProposal{&res},
Value: &Response_ProcessProposal{res},
}
}
func ToResponseFinalizeBlock(res ResponseFinalizeBlock) *Response {
func ToResponseFinalizeBlock(res *ResponseFinalizeBlock) *Response {
return &Response{
Value: &Response_FinalizeBlock{&res},
Value: &Response_FinalizeBlock{res},
}
}
+198 -71
View File
@@ -17,204 +17,331 @@ type Application struct {
}
// ApplySnapshotChunk provides a mock function with given fields: _a0, _a1
func (_m *Application) ApplySnapshotChunk(_a0 context.Context, _a1 types.RequestApplySnapshotChunk) types.ResponseApplySnapshotChunk {
func (_m *Application) ApplySnapshotChunk(_a0 context.Context, _a1 types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) {
ret := _m.Called(_a0, _a1)
var r0 types.ResponseApplySnapshotChunk
if rf, ok := ret.Get(0).(func(context.Context, types.RequestApplySnapshotChunk) types.ResponseApplySnapshotChunk); ok {
var r0 *types.ResponseApplySnapshotChunk
if rf, ok := ret.Get(0).(func(context.Context, types.RequestApplySnapshotChunk) *types.ResponseApplySnapshotChunk); ok {
r0 = rf(_a0, _a1)
} else {
r0 = ret.Get(0).(types.ResponseApplySnapshotChunk)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ResponseApplySnapshotChunk)
}
}
return r0
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, types.RequestApplySnapshotChunk) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// CheckTx provides a mock function with given fields: _a0, _a1
func (_m *Application) CheckTx(_a0 context.Context, _a1 types.RequestCheckTx) types.ResponseCheckTx {
func (_m *Application) CheckTx(_a0 context.Context, _a1 types.RequestCheckTx) (*types.ResponseCheckTx, error) {
ret := _m.Called(_a0, _a1)
var r0 types.ResponseCheckTx
if rf, ok := ret.Get(0).(func(context.Context, types.RequestCheckTx) types.ResponseCheckTx); ok {
var r0 *types.ResponseCheckTx
if rf, ok := ret.Get(0).(func(context.Context, types.RequestCheckTx) *types.ResponseCheckTx); ok {
r0 = rf(_a0, _a1)
} else {
r0 = ret.Get(0).(types.ResponseCheckTx)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ResponseCheckTx)
}
}
return r0
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, types.RequestCheckTx) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Commit provides a mock function with given fields: _a0
func (_m *Application) Commit(_a0 context.Context) types.ResponseCommit {
func (_m *Application) Commit(_a0 context.Context) (*types.ResponseCommit, error) {
ret := _m.Called(_a0)
var r0 types.ResponseCommit
if rf, ok := ret.Get(0).(func(context.Context) types.ResponseCommit); ok {
var r0 *types.ResponseCommit
if rf, ok := ret.Get(0).(func(context.Context) *types.ResponseCommit); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(types.ResponseCommit)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ResponseCommit)
}
}
return r0
var r1 error
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
r1 = rf(_a0)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// ExtendVote provides a mock function with given fields: _a0, _a1
func (_m *Application) ExtendVote(_a0 context.Context, _a1 types.RequestExtendVote) types.ResponseExtendVote {
func (_m *Application) ExtendVote(_a0 context.Context, _a1 types.RequestExtendVote) (*types.ResponseExtendVote, error) {
ret := _m.Called(_a0, _a1)
var r0 types.ResponseExtendVote
if rf, ok := ret.Get(0).(func(context.Context, types.RequestExtendVote) types.ResponseExtendVote); ok {
var r0 *types.ResponseExtendVote
if rf, ok := ret.Get(0).(func(context.Context, types.RequestExtendVote) *types.ResponseExtendVote); ok {
r0 = rf(_a0, _a1)
} else {
r0 = ret.Get(0).(types.ResponseExtendVote)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ResponseExtendVote)
}
}
return r0
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, types.RequestExtendVote) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// FinalizeBlock provides a mock function with given fields: _a0, _a1
func (_m *Application) FinalizeBlock(_a0 context.Context, _a1 types.RequestFinalizeBlock) types.ResponseFinalizeBlock {
func (_m *Application) FinalizeBlock(_a0 context.Context, _a1 types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error) {
ret := _m.Called(_a0, _a1)
var r0 types.ResponseFinalizeBlock
if rf, ok := ret.Get(0).(func(context.Context, types.RequestFinalizeBlock) types.ResponseFinalizeBlock); ok {
var r0 *types.ResponseFinalizeBlock
if rf, ok := ret.Get(0).(func(context.Context, types.RequestFinalizeBlock) *types.ResponseFinalizeBlock); ok {
r0 = rf(_a0, _a1)
} else {
r0 = ret.Get(0).(types.ResponseFinalizeBlock)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ResponseFinalizeBlock)
}
}
return r0
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, types.RequestFinalizeBlock) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Info provides a mock function with given fields: _a0, _a1
func (_m *Application) Info(_a0 context.Context, _a1 types.RequestInfo) types.ResponseInfo {
func (_m *Application) Info(_a0 context.Context, _a1 types.RequestInfo) (*types.ResponseInfo, error) {
ret := _m.Called(_a0, _a1)
var r0 types.ResponseInfo
if rf, ok := ret.Get(0).(func(context.Context, types.RequestInfo) types.ResponseInfo); ok {
var r0 *types.ResponseInfo
if rf, ok := ret.Get(0).(func(context.Context, types.RequestInfo) *types.ResponseInfo); ok {
r0 = rf(_a0, _a1)
} else {
r0 = ret.Get(0).(types.ResponseInfo)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ResponseInfo)
}
}
return r0
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, types.RequestInfo) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// InitChain provides a mock function with given fields: _a0, _a1
func (_m *Application) InitChain(_a0 context.Context, _a1 types.RequestInitChain) types.ResponseInitChain {
func (_m *Application) InitChain(_a0 context.Context, _a1 types.RequestInitChain) (*types.ResponseInitChain, error) {
ret := _m.Called(_a0, _a1)
var r0 types.ResponseInitChain
if rf, ok := ret.Get(0).(func(context.Context, types.RequestInitChain) types.ResponseInitChain); ok {
var r0 *types.ResponseInitChain
if rf, ok := ret.Get(0).(func(context.Context, types.RequestInitChain) *types.ResponseInitChain); ok {
r0 = rf(_a0, _a1)
} else {
r0 = ret.Get(0).(types.ResponseInitChain)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ResponseInitChain)
}
}
return r0
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, types.RequestInitChain) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// ListSnapshots provides a mock function with given fields: _a0, _a1
func (_m *Application) ListSnapshots(_a0 context.Context, _a1 types.RequestListSnapshots) types.ResponseListSnapshots {
func (_m *Application) ListSnapshots(_a0 context.Context, _a1 types.RequestListSnapshots) (*types.ResponseListSnapshots, error) {
ret := _m.Called(_a0, _a1)
var r0 types.ResponseListSnapshots
if rf, ok := ret.Get(0).(func(context.Context, types.RequestListSnapshots) types.ResponseListSnapshots); ok {
var r0 *types.ResponseListSnapshots
if rf, ok := ret.Get(0).(func(context.Context, types.RequestListSnapshots) *types.ResponseListSnapshots); ok {
r0 = rf(_a0, _a1)
} else {
r0 = ret.Get(0).(types.ResponseListSnapshots)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ResponseListSnapshots)
}
}
return r0
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, types.RequestListSnapshots) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// LoadSnapshotChunk provides a mock function with given fields: _a0, _a1
func (_m *Application) LoadSnapshotChunk(_a0 context.Context, _a1 types.RequestLoadSnapshotChunk) types.ResponseLoadSnapshotChunk {
func (_m *Application) LoadSnapshotChunk(_a0 context.Context, _a1 types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) {
ret := _m.Called(_a0, _a1)
var r0 types.ResponseLoadSnapshotChunk
if rf, ok := ret.Get(0).(func(context.Context, types.RequestLoadSnapshotChunk) types.ResponseLoadSnapshotChunk); ok {
var r0 *types.ResponseLoadSnapshotChunk
if rf, ok := ret.Get(0).(func(context.Context, types.RequestLoadSnapshotChunk) *types.ResponseLoadSnapshotChunk); ok {
r0 = rf(_a0, _a1)
} else {
r0 = ret.Get(0).(types.ResponseLoadSnapshotChunk)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ResponseLoadSnapshotChunk)
}
}
return r0
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, types.RequestLoadSnapshotChunk) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// OfferSnapshot provides a mock function with given fields: _a0, _a1
func (_m *Application) OfferSnapshot(_a0 context.Context, _a1 types.RequestOfferSnapshot) types.ResponseOfferSnapshot {
func (_m *Application) OfferSnapshot(_a0 context.Context, _a1 types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error) {
ret := _m.Called(_a0, _a1)
var r0 types.ResponseOfferSnapshot
if rf, ok := ret.Get(0).(func(context.Context, types.RequestOfferSnapshot) types.ResponseOfferSnapshot); ok {
var r0 *types.ResponseOfferSnapshot
if rf, ok := ret.Get(0).(func(context.Context, types.RequestOfferSnapshot) *types.ResponseOfferSnapshot); ok {
r0 = rf(_a0, _a1)
} else {
r0 = ret.Get(0).(types.ResponseOfferSnapshot)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ResponseOfferSnapshot)
}
}
return r0
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, types.RequestOfferSnapshot) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// PrepareProposal provides a mock function with given fields: _a0, _a1
func (_m *Application) PrepareProposal(_a0 context.Context, _a1 types.RequestPrepareProposal) types.ResponsePrepareProposal {
func (_m *Application) PrepareProposal(_a0 context.Context, _a1 types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) {
ret := _m.Called(_a0, _a1)
var r0 types.ResponsePrepareProposal
if rf, ok := ret.Get(0).(func(context.Context, types.RequestPrepareProposal) types.ResponsePrepareProposal); ok {
var r0 *types.ResponsePrepareProposal
if rf, ok := ret.Get(0).(func(context.Context, types.RequestPrepareProposal) *types.ResponsePrepareProposal); ok {
r0 = rf(_a0, _a1)
} else {
r0 = ret.Get(0).(types.ResponsePrepareProposal)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ResponsePrepareProposal)
}
}
return r0
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, types.RequestPrepareProposal) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// ProcessProposal provides a mock function with given fields: _a0, _a1
func (_m *Application) ProcessProposal(_a0 context.Context, _a1 types.RequestProcessProposal) types.ResponseProcessProposal {
func (_m *Application) ProcessProposal(_a0 context.Context, _a1 types.RequestProcessProposal) (*types.ResponseProcessProposal, error) {
ret := _m.Called(_a0, _a1)
var r0 types.ResponseProcessProposal
if rf, ok := ret.Get(0).(func(context.Context, types.RequestProcessProposal) types.ResponseProcessProposal); ok {
var r0 *types.ResponseProcessProposal
if rf, ok := ret.Get(0).(func(context.Context, types.RequestProcessProposal) *types.ResponseProcessProposal); ok {
r0 = rf(_a0, _a1)
} else {
r0 = ret.Get(0).(types.ResponseProcessProposal)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ResponseProcessProposal)
}
}
return r0
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, types.RequestProcessProposal) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Query provides a mock function with given fields: _a0, _a1
func (_m *Application) Query(_a0 context.Context, _a1 types.RequestQuery) types.ResponseQuery {
func (_m *Application) Query(_a0 context.Context, _a1 types.RequestQuery) (*types.ResponseQuery, error) {
ret := _m.Called(_a0, _a1)
var r0 types.ResponseQuery
if rf, ok := ret.Get(0).(func(context.Context, types.RequestQuery) types.ResponseQuery); ok {
var r0 *types.ResponseQuery
if rf, ok := ret.Get(0).(func(context.Context, types.RequestQuery) *types.ResponseQuery); ok {
r0 = rf(_a0, _a1)
} else {
r0 = ret.Get(0).(types.ResponseQuery)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ResponseQuery)
}
}
return r0
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, types.RequestQuery) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// VerifyVoteExtension provides a mock function with given fields: _a0, _a1
func (_m *Application) VerifyVoteExtension(_a0 context.Context, _a1 types.RequestVerifyVoteExtension) types.ResponseVerifyVoteExtension {
func (_m *Application) VerifyVoteExtension(_a0 context.Context, _a1 types.RequestVerifyVoteExtension) (*types.ResponseVerifyVoteExtension, error) {
ret := _m.Called(_a0, _a1)
var r0 types.ResponseVerifyVoteExtension
if rf, ok := ret.Get(0).(func(context.Context, types.RequestVerifyVoteExtension) types.ResponseVerifyVoteExtension); ok {
var r0 *types.ResponseVerifyVoteExtension
if rf, ok := ret.Get(0).(func(context.Context, types.RequestVerifyVoteExtension) *types.ResponseVerifyVoteExtension); ok {
r0 = rf(_a0, _a1)
} else {
r0 = ret.Get(0).(types.ResponseVerifyVoteExtension)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ResponseVerifyVoteExtension)
}
}
return r0
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, types.RequestVerifyVoteExtension) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// NewApplication creates a new instance of Application. It also registers a cleanup function to assert the mocks expectations.
// NewApplication creates a new instance of Application. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
func NewApplication(t testing.TB) *Application {
mock := &Application{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
-177
View File
@@ -1,177 +0,0 @@
package mocks
import (
context "context"
types "github.com/tendermint/tendermint/abci/types"
)
// BaseMock provides a wrapper around the generated Application mock and a BaseApplication.
// BaseMock first tries to use the mock's implementation of the method.
// If no functionality was provided for the mock by the user, BaseMock dispatches
// to the BaseApplication and uses its functionality.
// BaseMock allows users to provide mocked functionality for only the methods that matter
// for their test while avoiding a panic if the code calls Application methods that are
// not relevant to the test.
type BaseMock struct {
base *types.BaseApplication
*Application
}
func NewBaseMock() BaseMock {
return BaseMock{
base: types.NewBaseApplication(),
Application: new(Application),
}
}
// Info/Query Connection
// Return application info
func (m BaseMock) Info(ctx context.Context, input types.RequestInfo) (ret types.ResponseInfo) {
defer func() {
if r := recover(); r != nil {
ret = m.base.Info(ctx, input)
}
}()
ret = m.Application.Info(ctx, input)
return ret
}
func (m BaseMock) Query(ctx context.Context, input types.RequestQuery) (ret types.ResponseQuery) {
defer func() {
if r := recover(); r != nil {
ret = m.base.Query(ctx, input)
}
}()
ret = m.Application.Query(ctx, input)
return ret
}
// Mempool Connection
// Validate a tx for the mempool
func (m BaseMock) CheckTx(ctx context.Context, input types.RequestCheckTx) (ret types.ResponseCheckTx) {
defer func() {
if r := recover(); r != nil {
ret = m.base.CheckTx(ctx, input)
}
}()
ret = m.Application.CheckTx(ctx, input)
return ret
}
// Consensus Connection
// Initialize blockchain w validators/other info from TendermintCore
func (m BaseMock) InitChain(ctx context.Context, input types.RequestInitChain) (ret types.ResponseInitChain) {
defer func() {
if r := recover(); r != nil {
ret = m.base.InitChain(ctx, input)
}
}()
ret = m.Application.InitChain(ctx, input)
return ret
}
func (m BaseMock) PrepareProposal(ctx context.Context, input types.RequestPrepareProposal) (ret types.ResponsePrepareProposal) {
defer func() {
if r := recover(); r != nil {
ret = m.base.PrepareProposal(ctx, input)
}
}()
ret = m.Application.PrepareProposal(ctx, input)
return ret
}
func (m BaseMock) ProcessProposal(ctx context.Context, input types.RequestProcessProposal) (ret types.ResponseProcessProposal) {
defer func() {
if r := recover(); r != nil {
ret = m.base.ProcessProposal(ctx, input)
}
}()
ret = m.Application.ProcessProposal(ctx, input)
return ret
}
// Commit the state and return the application Merkle root hash
func (m BaseMock) Commit(ctx context.Context) (ret types.ResponseCommit) {
defer func() {
if r := recover(); r != nil {
ret = m.base.Commit(ctx)
}
}()
ret = m.Application.Commit(ctx)
return ret
}
// Create application specific vote extension
func (m BaseMock) ExtendVote(ctx context.Context, input types.RequestExtendVote) (ret types.ResponseExtendVote) {
defer func() {
if r := recover(); r != nil {
ret = m.base.ExtendVote(ctx, input)
}
}()
ret = m.Application.ExtendVote(ctx, input)
return ret
}
// Verify application's vote extension data
func (m BaseMock) VerifyVoteExtension(ctx context.Context, input types.RequestVerifyVoteExtension) (ret types.ResponseVerifyVoteExtension) {
defer func() {
if r := recover(); r != nil {
ret = m.base.VerifyVoteExtension(ctx, input)
}
}()
ret = m.Application.VerifyVoteExtension(ctx, input)
return ret
}
// State Sync Connection
// List available snapshots
func (m BaseMock) ListSnapshots(ctx context.Context, input types.RequestListSnapshots) (ret types.ResponseListSnapshots) {
defer func() {
if r := recover(); r != nil {
ret = m.base.ListSnapshots(ctx, input)
}
}()
ret = m.Application.ListSnapshots(ctx, input)
return ret
}
func (m BaseMock) OfferSnapshot(ctx context.Context, input types.RequestOfferSnapshot) (ret types.ResponseOfferSnapshot) {
defer func() {
if r := recover(); r != nil {
ret = m.base.OfferSnapshot(ctx, input)
}
}()
ret = m.Application.OfferSnapshot(ctx, input)
return ret
}
func (m BaseMock) LoadSnapshotChunk(ctx context.Context, input types.RequestLoadSnapshotChunk) (ret types.ResponseLoadSnapshotChunk) {
defer func() {
if r := recover(); r != nil {
ret = m.base.LoadSnapshotChunk(ctx, input)
}
}()
ret = m.Application.LoadSnapshotChunk(ctx, input)
return ret
}
func (m BaseMock) ApplySnapshotChunk(ctx context.Context, input types.RequestApplySnapshotChunk) (ret types.ResponseApplySnapshotChunk) {
defer func() {
if r := recover(); r != nil {
ret = m.base.ApplySnapshotChunk(ctx, input)
}
}()
ret = m.Application.ApplySnapshotChunk(ctx, input)
return ret
}
func (m BaseMock) FinalizeBlock(ctx context.Context, input types.RequestFinalizeBlock) (ret types.ResponseFinalizeBlock) {
defer func() {
if r := recover(); r != nil {
ret = m.base.FinalizeBlock(ctx, input)
}
}()
ret = m.Application.FinalizeBlock(ctx, input)
return ret
}
+2 -1
View File
@@ -68,7 +68,8 @@ func TestByzantinePrevoteEquivocation(t *testing.T) {
ensureDir(t, path.Dir(thisConfig.Consensus.WalFile()), 0700) // dir for wal
app := kvstore.NewApplication()
vals := types.TM2PB.ValidatorUpdates(state.Validators)
app.InitChain(ctx, abci.RequestInitChain{Validators: vals})
_, err = app.InitChain(ctx, abci.RequestInitChain{Validators: vals})
require.NoError(t, err)
blockDB := dbm.NewMemDB()
blockStore := store.NewBlockStore(blockDB)
+4 -2
View File
@@ -821,7 +821,8 @@ func makeConsensusState(
closeFuncs = append(closeFuncs, app.Close)
vals := types.TM2PB.ValidatorUpdates(state.Validators)
app.InitChain(ctx, abci.RequestInitChain{Validators: vals})
_, err = app.InitChain(ctx, abci.RequestInitChain{Validators: vals})
require.NoError(t, err)
l := logger.With("validator", i, "module", "consensus")
css[i] = newStateWithConfigAndBlockStore(ctx, t, l, thisConfig, state, privVals[i], app, blockStore)
@@ -892,7 +893,8 @@ func randConsensusNetWithPeers(
case *kvstore.Application:
state.Version.Consensus.App = kvstore.ProtocolVersion
}
app.InitChain(ctx, abci.RequestInitChain{Validators: vals})
_, err = app.InitChain(ctx, abci.RequestInitChain{Validators: vals})
require.NoError(t, err)
// sm.SaveState(stateDB,state) //height 1's validatorsInfo already saved in LoadStateFromDBOrGenesisDoc above
css[i] = newStateWithConfig(ctx, t, logger.With("validator", i, "module", "consensus"), thisConfig, state, privVal, app)
+20 -18
View File
@@ -199,10 +199,12 @@ func TestMempoolRmBadTx(t *testing.T) {
txBytes := make([]byte, 8)
binary.BigEndian.PutUint64(txBytes, uint64(0))
resFinalize := app.FinalizeBlock(ctx, abci.RequestFinalizeBlock{Txs: [][]byte{txBytes}})
resFinalize, err := app.FinalizeBlock(ctx, abci.RequestFinalizeBlock{Txs: [][]byte{txBytes}})
require.NoError(t, err)
assert.False(t, resFinalize.TxResults[0].IsErr(), fmt.Sprintf("expected no error. got %v", resFinalize))
resCommit := app.Commit(ctx)
resCommit, err := app.Commit(ctx)
require.NoError(t, err)
assert.True(t, len(resCommit.Data) > 0)
emptyMempoolCh := make(chan struct{})
@@ -267,11 +269,11 @@ func NewCounterApplication() *CounterApplication {
return &CounterApplication{}
}
func (app *CounterApplication) Info(_ context.Context, req abci.RequestInfo) abci.ResponseInfo {
return abci.ResponseInfo{Data: fmt.Sprintf("txs:%v", app.txCount)}
func (app *CounterApplication) Info(_ context.Context, req abci.RequestInfo) (*abci.ResponseInfo, error) {
return &abci.ResponseInfo{Data: fmt.Sprintf("txs:%v", app.txCount)}, nil
}
func (app *CounterApplication) FinalizeBlock(_ context.Context, req abci.RequestFinalizeBlock) abci.ResponseFinalizeBlock {
func (app *CounterApplication) FinalizeBlock(_ context.Context, req abci.RequestFinalizeBlock) (*abci.ResponseFinalizeBlock, error) {
respTxs := make([]*abci.ExecTxResult, len(req.Txs))
for i, tx := range req.Txs {
txValue := txAsUint64(tx)
@@ -285,18 +287,19 @@ func (app *CounterApplication) FinalizeBlock(_ context.Context, req abci.Request
app.txCount++
respTxs[i] = &abci.ExecTxResult{Code: code.CodeTypeOK}
}
return abci.ResponseFinalizeBlock{TxResults: respTxs}
return &abci.ResponseFinalizeBlock{TxResults: respTxs}, nil
}
func (app *CounterApplication) CheckTx(_ context.Context, req abci.RequestCheckTx) abci.ResponseCheckTx {
func (app *CounterApplication) CheckTx(_ context.Context, req abci.RequestCheckTx) (*abci.ResponseCheckTx, error) {
txValue := txAsUint64(req.Tx)
if txValue != uint64(app.mempoolTxCount) {
return abci.ResponseCheckTx{
return &abci.ResponseCheckTx{
Code: code.CodeTypeBadNonce,
Log: fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.mempoolTxCount, txValue)}
Log: fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.mempoolTxCount, txValue),
}, nil
}
app.mempoolTxCount++
return abci.ResponseCheckTx{Code: code.CodeTypeOK}
return &abci.ResponseCheckTx{Code: code.CodeTypeOK}, nil
}
func txAsUint64(tx []byte) uint64 {
@@ -305,18 +308,17 @@ func txAsUint64(tx []byte) uint64 {
return binary.BigEndian.Uint64(tx8)
}
func (app *CounterApplication) Commit(context.Context) abci.ResponseCommit {
func (app *CounterApplication) Commit(context.Context) (*abci.ResponseCommit, error) {
app.mempoolTxCount = app.txCount
if app.txCount == 0 {
return abci.ResponseCommit{}
return &abci.ResponseCommit{}, nil
}
hash := make([]byte, 8)
binary.BigEndian.PutUint64(hash, uint64(app.txCount))
return abci.ResponseCommit{Data: hash}
return &abci.ResponseCommit{Data: hash}, nil
}
func (app *CounterApplication) PrepareProposal(_ context.Context, req abci.RequestPrepareProposal) abci.ResponsePrepareProposal {
func (app *CounterApplication) PrepareProposal(_ context.Context, req abci.RequestPrepareProposal) (*abci.ResponsePrepareProposal, error) {
trs := make([]*abci.TxRecord, 0, len(req.Txs))
var totalBytes int64
for _, tx := range req.Txs {
@@ -329,9 +331,9 @@ func (app *CounterApplication) PrepareProposal(_ context.Context, req abci.Reque
Tx: tx,
})
}
return abci.ResponsePrepareProposal{TxRecords: trs}
return &abci.ResponsePrepareProposal{TxRecords: trs}, nil
}
func (app *CounterApplication) ProcessProposal(_ context.Context, req abci.RequestProcessProposal) abci.ResponseProcessProposal {
return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}
func (app *CounterApplication) ProcessProposal(_ context.Context, req abci.RequestProcessProposal) (*abci.ResponseProcessProposal, error) {
return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil
}
@@ -29,9 +29,10 @@ func (_m *ConsSyncReactor) SwitchToConsensus(_a0 state.State, _a1 bool) {
_m.Called(_a0, _a1)
}
// NewConsSyncReactor creates a new instance of ConsSyncReactor. It also registers a cleanup function to assert the mocks expectations.
// NewConsSyncReactor creates a new instance of ConsSyncReactor. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
func NewConsSyncReactor(t testing.TB) *ConsSyncReactor {
mock := &ConsSyncReactor{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
+2 -1
View File
@@ -466,7 +466,8 @@ func TestReactorWithEvidence(t *testing.T) {
app := kvstore.NewApplication()
vals := types.TM2PB.ValidatorUpdates(state.Validators)
app.InitChain(ctx, abci.RequestInitChain{Validators: vals})
_, err = app.InitChain(ctx, abci.RequestInitChain{Validators: vals})
require.NoError(t, err)
pv := privVals[i]
blockDB := dbm.NewMemDB()
+5 -5
View File
@@ -75,15 +75,15 @@ type mockProxyApp struct {
abciResponses *tmstate.ABCIResponses
}
func (mock *mockProxyApp) FinalizeBlock(_ context.Context, req abci.RequestFinalizeBlock) abci.ResponseFinalizeBlock {
func (mock *mockProxyApp) FinalizeBlock(_ context.Context, req abci.RequestFinalizeBlock) (*abci.ResponseFinalizeBlock, error) {
r := mock.abciResponses.FinalizeBlock
mock.txCount++
if r == nil {
return abci.ResponseFinalizeBlock{}
return &abci.ResponseFinalizeBlock{}, nil
}
return *r
return r, nil
}
func (mock *mockProxyApp) Commit(context.Context) abci.ResponseCommit {
return abci.ResponseCommit{Data: mock.appHash}
func (mock *mockProxyApp) Commit(context.Context) (*abci.ResponseCommit, error) {
return &abci.ResponseCommit{Data: mock.appHash}, nil
}
+6 -8
View File
@@ -1017,15 +1017,15 @@ type badApp struct {
onlyLastHashIsWrong bool
}
func (app *badApp) Commit(context.Context) abci.ResponseCommit {
func (app *badApp) Commit(context.Context) (*abci.ResponseCommit, error) {
app.height++
if app.onlyLastHashIsWrong {
if app.height == app.numBlocks {
return abci.ResponseCommit{Data: tmrand.Bytes(8)}
return &abci.ResponseCommit{Data: tmrand.Bytes(8)}, nil
}
return abci.ResponseCommit{Data: []byte{app.height}}
return &abci.ResponseCommit{Data: []byte{app.height}}, nil
} else if app.allHashesAreWrong {
return abci.ResponseCommit{Data: tmrand.Bytes(8)}
return &abci.ResponseCommit{Data: tmrand.Bytes(8)}, nil
}
panic("either allHashesAreWrong or onlyLastHashIsWrong must be set")
@@ -1275,8 +1275,6 @@ type initChainApp struct {
vals []abci.ValidatorUpdate
}
func (ica *initChainApp) InitChain(_ context.Context, req abci.RequestInitChain) abci.ResponseInitChain {
return abci.ResponseInitChain{
Validators: ica.vals,
}
func (ica *initChainApp) InitChain(_ context.Context, req abci.RequestInitChain) (*abci.ResponseInitChain, error) {
return &abci.ResponseInitChain{Validators: ica.vals}, nil
}
+49 -40
View File
@@ -1912,13 +1912,13 @@ func TestProcessProposalAccept(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
m := abcimocks.NewBaseMock()
m := abcimocks.NewApplication(t)
status := abci.ResponseProcessProposal_REJECT
if testCase.accept {
status = abci.ResponseProcessProposal_ACCEPT
}
m.On("ProcessProposal", mock.Anything, mock.Anything).Return(abci.ResponseProcessProposal{Status: status})
m.On("PrepareProposal", mock.Anything, mock.Anything).Return(abci.ResponsePrepareProposal{})
m.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ResponseProcessProposal{Status: status}, nil)
m.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{}, nil).Maybe()
cs1, _ := makeState(ctx, t, makeStateArgs{config: config, application: m})
height, round := cs1.Height, cs1.Round
@@ -1965,15 +1965,18 @@ func TestFinalizeBlockCalled(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
m := abcimocks.NewBaseMock()
m.On("ProcessProposal", mock.Anything, mock.Anything).Return(abci.ResponseProcessProposal{
m := abcimocks.NewApplication(t)
m.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ResponseProcessProposal{
Status: abci.ResponseProcessProposal_ACCEPT,
})
m.On("PrepareProposal", mock.Anything, mock.Anything).Return(abci.ResponsePrepareProposal{})
m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(abci.ResponseVerifyVoteExtension{
}, nil)
m.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{}, nil)
m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(&abci.ResponseVerifyVoteExtension{
Status: abci.ResponseVerifyVoteExtension_ACCEPT,
})
m.On("FinalizeBlock", mock.Anything, mock.Anything).Return(abci.ResponseFinalizeBlock{}).Maybe()
}, nil)
m.On("FinalizeBlock", mock.Anything, mock.Anything).Return(&abci.ResponseFinalizeBlock{}, nil).Maybe()
m.On("ExtendVote", mock.Anything, mock.Anything).Return(&abci.ResponseExtendVote{}, nil)
m.On("Commit", mock.Anything).Return(&abci.ResponseCommit{}, nil).Maybe()
cs1, vss := makeState(ctx, t, makeStateArgs{config: config, application: m})
height, round := cs1.Height, cs1.Round
@@ -2026,16 +2029,17 @@ func TestExtendVoteCalled(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
m := abcimocks.NewBaseMock()
m.On("ProcessProposal", mock.Anything, mock.Anything).Return(abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT})
m.On("PrepareProposal", mock.Anything, mock.Anything).Return(abci.ResponsePrepareProposal{})
m.On("ExtendVote", mock.Anything, mock.Anything).Return(abci.ResponseExtendVote{
m := abcimocks.NewApplication(t)
m.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil)
m.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{}, nil)
m.On("ExtendVote", mock.Anything, mock.Anything).Return(&abci.ResponseExtendVote{
VoteExtension: []byte("extension"),
})
m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(abci.ResponseVerifyVoteExtension{
}, nil)
m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(&abci.ResponseVerifyVoteExtension{
Status: abci.ResponseVerifyVoteExtension_ACCEPT,
})
m.On("FinalizeBlock", mock.Anything, mock.Anything).Return(abci.ResponseFinalizeBlock{}).Maybe()
}, nil)
m.On("Commit", mock.Anything).Return(&abci.ResponseCommit{}, nil).Maybe()
m.On("FinalizeBlock", mock.Anything, mock.Anything).Return(&abci.ResponseFinalizeBlock{}, nil).Maybe()
cs1, vss := makeState(ctx, t, makeStateArgs{config: config, application: m})
height, round := cs1.Height, cs1.Round
@@ -2074,7 +2078,6 @@ func TestExtendVoteCalled(t *testing.T) {
Height: height,
VoteExtension: []byte("extension"),
})
signAddVotes(ctx, t, cs1, tmproto.PrecommitType, config.ChainID(), blockID, vss[1:]...)
ensureNewRound(t, newRoundCh, height+1, 0)
m.AssertExpectations(t)
@@ -2102,16 +2105,16 @@ func TestVerifyVoteExtensionNotCalledOnAbsentPrecommit(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
m := abcimocks.NewBaseMock()
m.On("ProcessProposal", mock.Anything, mock.Anything).Return(abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT})
m.On("PrepareProposal", mock.Anything, mock.Anything).Return(abci.ResponsePrepareProposal{})
m.On("ExtendVote", mock.Anything, mock.Anything).Return(abci.ResponseExtendVote{
m := abcimocks.NewApplication(t)
m.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil)
m.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{}, nil)
m.On("ExtendVote", mock.Anything, mock.Anything).Return(&abci.ResponseExtendVote{
VoteExtension: []byte("extension"),
})
m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(abci.ResponseVerifyVoteExtension{
}, nil)
m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(&abci.ResponseVerifyVoteExtension{
Status: abci.ResponseVerifyVoteExtension_ACCEPT,
})
m.On("FinalizeBlock", mock.Anything, mock.Anything).Return(abci.ResponseFinalizeBlock{}).Maybe()
}, nil)
m.On("FinalizeBlock", mock.Anything, mock.Anything).Return(&abci.ResponseFinalizeBlock{}, nil).Maybe()
cs1, vss := makeState(ctx, t, makeStateArgs{config: config, application: m})
height, round := cs1.Height, cs1.Round
@@ -2148,6 +2151,7 @@ func TestVerifyVoteExtensionNotCalledOnAbsentPrecommit(t *testing.T) {
VoteExtension: []byte("extension"),
})
m.On("Commit", mock.Anything).Return(&abci.ResponseCommit{}, nil).Maybe()
signAddVotes(ctx, t, cs1, tmproto.PrecommitType, config.ChainID(), blockID, vss[2:]...)
ensureNewRound(t, newRoundCh, height+1, 0)
m.AssertExpectations(t)
@@ -2187,13 +2191,24 @@ func TestPrepareProposalReceivesVoteExtensions(t *testing.T) {
[]byte("extension 3"),
}
m := abcimocks.NewBaseMock()
m.On("ExtendVote", mock.Anything, mock.Anything).Return(abci.ResponseExtendVote{
// m := abcimocks.NewApplication(t)
m := &abcimocks.Application{}
m.On("ExtendVote", mock.Anything, mock.Anything).Return(&abci.ResponseExtendVote{
VoteExtension: voteExtensions[0],
})
m.On("PrepareProposal", mock.Anything, mock.Anything).Return(abci.ResponsePrepareProposal{}).Once()
m.On("ProcessProposal", mock.Anything, mock.Anything).Return(abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}).Once()
m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_ACCEPT})
}, nil)
m.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil)
// capture the prepare proposal request.
rpp := abci.RequestPrepareProposal{}
m.On("PrepareProposal", mock.Anything, mock.MatchedBy(func(r abci.RequestPrepareProposal) bool {
rpp = r
return true
})).Return(&abci.ResponsePrepareProposal{}, nil)
m.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{}, nil).Once()
m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(&abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_ACCEPT}, nil)
m.On("Commit", mock.Anything).Return(&abci.ResponseCommit{}, nil).Maybe()
m.On("FinalizeBlock", mock.Anything, mock.Anything).Return(&abci.ResponseFinalizeBlock{}, nil)
cs1, vss := makeState(ctx, t, makeStateArgs{config: config, application: m})
height, round := cs1.Height, cs1.Round
@@ -2235,19 +2250,13 @@ func TestPrepareProposalReceivesVoteExtensions(t *testing.T) {
incrementRound(vss[1:]...)
round = 3
// capture the prepare proposal request.
rpp := abci.RequestPrepareProposal{}
m.On("PrepareProposal", mock.Anything, mock.MatchedBy(func(r abci.RequestPrepareProposal) bool {
rpp = r
return true
})).Return(abci.ResponsePrepareProposal{})
signAddVotes(ctx, t, cs1, tmproto.PrecommitType, config.ChainID(), types.BlockID{}, vss[1:]...)
ensureNewRound(t, newRoundCh, height, round)
ensureNewProposal(t, proposalCh, height, round)
// ensure that the proposer received the list of vote extensions from the
// previous height.
require.Len(t, rpp.LocalLastCommit.Votes, len(vss))
for i := range vss {
require.Equal(t, rpp.LocalLastCommit.Votes[i].VoteExtension, voteExtensions[i])
}
+2 -1
View File
@@ -61,9 +61,10 @@ func (_m *BlockStore) LoadBlockMeta(height int64) *types.BlockMeta {
return r0
}
// NewBlockStore creates a new instance of BlockStore. It also registers a cleanup function to assert the mocks expectations.
// NewBlockStore creates a new instance of BlockStore. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
func NewBlockStore(t testing.TB) *BlockStore {
mock := &BlockStore{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
+7 -7
View File
@@ -36,7 +36,7 @@ type testTx struct {
priority int64
}
func (app *application) CheckTx(_ context.Context, req abci.RequestCheckTx) abci.ResponseCheckTx {
func (app *application) CheckTx(_ context.Context, req abci.RequestCheckTx) (*abci.ResponseCheckTx, error) {
var (
priority int64
sender string
@@ -47,29 +47,29 @@ func (app *application) CheckTx(_ context.Context, req abci.RequestCheckTx) abci
if len(parts) == 3 {
v, err := strconv.ParseInt(string(parts[2]), 10, 64)
if err != nil {
return abci.ResponseCheckTx{
return &abci.ResponseCheckTx{
Priority: priority,
Code: 100,
GasWanted: 1,
}
}, nil
}
priority = v
sender = string(parts[0])
} else {
return abci.ResponseCheckTx{
return &abci.ResponseCheckTx{
Priority: priority,
Code: 101,
GasWanted: 1,
}
}, nil
}
return abci.ResponseCheckTx{
return &abci.ResponseCheckTx{
Priority: priority,
Sender: sender,
Code: code.CodeTypeOK,
GasWanted: 1,
}
}, nil
}
func setup(t testing.TB, app abciclient.Client, cacheSize int, options ...TxMempoolOption) *TxMempool {
+2 -1
View File
@@ -173,9 +173,10 @@ func (_m *Mempool) Update(ctx context.Context, blockHeight int64, blockTxs types
return r0
}
// NewMempool creates a new instance of Mempool. It also registers a cleanup function to assert the mocks expectations.
// NewMempool creates a new instance of Mempool. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
func NewMempool(t testing.TB) *Mempool {
mock := &Mempool{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
+2 -1
View File
@@ -153,9 +153,10 @@ func (_m *Connection) String() string {
return r0
}
// NewConnection creates a new instance of Connection. It also registers a cleanup function to assert the mocks expectations.
// NewConnection creates a new instance of Connection. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
func NewConnection(t testing.TB) *Connection {
mock := &Connection{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
+2 -1
View File
@@ -144,9 +144,10 @@ func (_m *Transport) String() string {
return r0
}
// NewTransport creates a new instance of Transport. It also registers a cleanup function to assert the mocks expectations.
// NewTransport creates a new instance of Transport. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
func NewTransport(t testing.TB) *Transport {
mock := &Transport{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
+21 -21
View File
@@ -277,7 +277,7 @@ func TestProcessProposal(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
app := abcimocks.NewBaseMock()
app := abcimocks.NewApplication(t)
logger := log.NewNopLogger()
cc := abciclient.NewLocalClient(logger, app)
proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
@@ -343,7 +343,7 @@ func TestProcessProposal(t *testing.T) {
ProposerAddress: block1.ProposerAddress,
}
app.On("ProcessProposal", mock.Anything, mock.Anything).Return(abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT})
app.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil)
acceptBlock, err := blockExec.ProcessProposal(ctx, block1, state)
require.NoError(t, err)
require.True(t, acceptBlock)
@@ -621,8 +621,8 @@ func TestEmptyPrepareProposal(t *testing.T) {
eventBus := eventbus.NewDefault(logger)
require.NoError(t, eventBus.Start(ctx))
app := abcimocks.NewBaseMock()
app.On("PrepareProposal", mock.Anything).Return(abci.ResponsePrepareProposal{})
app := abcimocks.NewApplication(t)
app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{}, nil)
cc := abciclient.NewLocalClient(logger, app)
proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
err := proxyApp.Start(ctx)
@@ -680,10 +680,10 @@ func TestPrepareProposalErrorOnNonExistingRemoved(t *testing.T) {
mp := &mpmocks.Mempool{}
mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs{})
app := abcimocks.NewBaseMock()
app := abcimocks.NewApplication(t)
// create an invalid ResponsePrepareProposal
rpp := abci.ResponsePrepareProposal{
rpp := &abci.ResponsePrepareProposal{
TxRecords: []*abci.TxRecord{
{
Action: abci.TxRecord_REMOVED,
@@ -691,7 +691,7 @@ func TestPrepareProposalErrorOnNonExistingRemoved(t *testing.T) {
},
},
}
app.On("PrepareProposal", mock.Anything, mock.Anything).Return(rpp)
app.On("PrepareProposal", mock.Anything, mock.Anything).Return(rpp, nil)
cc := abciclient.NewLocalClient(logger, app)
proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
@@ -711,8 +711,8 @@ func TestPrepareProposalErrorOnNonExistingRemoved(t *testing.T) {
pa, _ := state.Validators.GetByIndex(0)
commit, votes := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa, votes)
require.Nil(t, block)
require.ErrorContains(t, err, "new transaction incorrectly marked as removed")
require.Nil(t, block)
mp.AssertExpectations(t)
}
@@ -744,10 +744,10 @@ func TestPrepareProposalRemoveTxs(t *testing.T) {
trs[1].Action = abci.TxRecord_REMOVED
mp.On("RemoveTxByKey", mock.Anything).Return(nil).Twice()
app := abcimocks.NewBaseMock()
app.On("PrepareProposal", mock.Anything, mock.Anything).Return(abci.ResponsePrepareProposal{
app := abcimocks.NewApplication(t)
app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{
TxRecords: trs,
})
}, nil)
cc := abciclient.NewLocalClient(logger, app)
proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
@@ -803,10 +803,10 @@ func TestPrepareProposalAddedTxsIncluded(t *testing.T) {
trs[0].Action = abci.TxRecord_ADDED
trs[1].Action = abci.TxRecord_ADDED
app := abcimocks.NewBaseMock()
app.On("PrepareProposal", mock.Anything, mock.Anything).Return(abci.ResponsePrepareProposal{
app := abcimocks.NewApplication(t)
app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{
TxRecords: trs,
})
}, nil)
cc := abciclient.NewLocalClient(logger, app)
proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
@@ -859,10 +859,10 @@ func TestPrepareProposalReorderTxs(t *testing.T) {
trs = trs[2:]
trs = append(trs[len(trs)/2:], trs[:len(trs)/2]...)
app := abcimocks.NewBaseMock()
app.On("PrepareProposal", mock.Anything, mock.Anything).Return(abci.ResponsePrepareProposal{
app := abcimocks.NewApplication(t)
app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{
TxRecords: trs,
})
}, nil)
cc := abciclient.NewLocalClient(logger, app)
proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
@@ -919,10 +919,10 @@ func TestPrepareProposalErrorOnTooManyTxs(t *testing.T) {
trs := txsToTxRecords(types.Txs(txs))
app := abcimocks.NewBaseMock()
app.On("PrepareProposal", mock.Anything, mock.Anything).Return(abci.ResponsePrepareProposal{
app := abcimocks.NewApplication(t)
app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{
TxRecords: trs,
})
}, nil)
cc := abciclient.NewLocalClient(logger, app)
proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
@@ -943,8 +943,8 @@ func TestPrepareProposalErrorOnTooManyTxs(t *testing.T) {
commit, votes := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa, votes)
require.Nil(t, block)
require.ErrorContains(t, err, "transaction data size exceeds maximum")
require.Nil(t, block, "")
mp.AssertExpectations(t)
}
+14 -14
View File
@@ -278,11 +278,11 @@ type testApp struct {
var _ abci.Application = (*testApp)(nil)
func (app *testApp) Info(_ context.Context, req abci.RequestInfo) (resInfo abci.ResponseInfo) {
return abci.ResponseInfo{}
func (app *testApp) Info(_ context.Context, req abci.RequestInfo) (*abci.ResponseInfo, error) {
return &abci.ResponseInfo{}, nil
}
func (app *testApp) FinalizeBlock(_ context.Context, req abci.RequestFinalizeBlock) abci.ResponseFinalizeBlock {
func (app *testApp) FinalizeBlock(_ context.Context, req abci.RequestFinalizeBlock) (*abci.ResponseFinalizeBlock, error) {
app.CommitVotes = req.DecidedLastCommit.Votes
app.ByzantineValidators = req.ByzantineValidators
@@ -295,7 +295,7 @@ func (app *testApp) FinalizeBlock(_ context.Context, req abci.RequestFinalizeBlo
}
}
return abci.ResponseFinalizeBlock{
return &abci.ResponseFinalizeBlock{
ValidatorUpdates: app.ValidatorUpdates,
ConsensusParamUpdates: &tmproto.ConsensusParams{
Version: &tmproto.VersionParams{
@@ -304,26 +304,26 @@ func (app *testApp) FinalizeBlock(_ context.Context, req abci.RequestFinalizeBlo
},
Events: []abci.Event{},
TxResults: resTxs,
}
}, nil
}
func (app *testApp) CheckTx(_ context.Context, req abci.RequestCheckTx) abci.ResponseCheckTx {
return abci.ResponseCheckTx{}
func (app *testApp) CheckTx(_ context.Context, req abci.RequestCheckTx) (*abci.ResponseCheckTx, error) {
return &abci.ResponseCheckTx{}, nil
}
func (app *testApp) Commit(context.Context) abci.ResponseCommit {
return abci.ResponseCommit{RetainHeight: 1}
func (app *testApp) Commit(context.Context) (*abci.ResponseCommit, error) {
return &abci.ResponseCommit{RetainHeight: 1}, nil
}
func (app *testApp) Query(_ context.Context, req abci.RequestQuery) (resQuery abci.ResponseQuery) {
return
func (app *testApp) Query(_ context.Context, req abci.RequestQuery) (*abci.ResponseQuery, error) {
return &abci.ResponseQuery{}, nil
}
func (app *testApp) ProcessProposal(_ context.Context, req abci.RequestProcessProposal) abci.ResponseProcessProposal {
func (app *testApp) ProcessProposal(_ context.Context, req abci.RequestProcessProposal) (*abci.ResponseProcessProposal, error) {
for _, tx := range req.Txs {
if len(tx) == 0 {
return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}
return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil
}
}
return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}
return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil
}
+2 -1
View File
@@ -168,9 +168,10 @@ func (_m *EventSink) Type() indexer.EventSinkType {
return r0
}
// NewEventSink creates a new instance of EventSink. It also registers a cleanup function to assert the mocks expectations.
// NewEventSink creates a new instance of EventSink. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
func NewEventSink(t testing.TB) *EventSink {
mock := &EventSink{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
+2 -1
View File
@@ -211,9 +211,10 @@ func (_m *BlockStore) Size() int64 {
return r0
}
// NewBlockStore creates a new instance of BlockStore. It also registers a cleanup function to assert the mocks expectations.
// NewBlockStore creates a new instance of BlockStore. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
func NewBlockStore(t testing.TB) *BlockStore {
mock := &BlockStore{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
+2 -1
View File
@@ -74,9 +74,10 @@ func (_m *EvidencePool) Update(_a0 context.Context, _a1 state.State, _a2 types.E
_m.Called(_a0, _a1, _a2)
}
// NewEvidencePool creates a new instance of EvidencePool. It also registers a cleanup function to assert the mocks expectations.
// NewEvidencePool creates a new instance of EvidencePool. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
func NewEvidencePool(t testing.TB) *EvidencePool {
mock := &EvidencePool{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
+2 -1
View File
@@ -189,9 +189,10 @@ func (_m *Store) SaveValidatorSets(_a0 int64, _a1 int64, _a2 *types.ValidatorSet
return r0
}
// NewStore creates a new instance of Store. It also registers a cleanup function to assert the mocks expectations.
// NewStore creates a new instance of Store. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
func NewStore(t testing.TB) *Store {
mock := &Store{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
+2 -1
View File
@@ -85,9 +85,10 @@ func (_m *StateProvider) State(ctx context.Context, height uint64) (state.State,
return r0, r1
}
// NewStateProvider creates a new instance of StateProvider. It also registers a cleanup function to assert the mocks expectations.
// NewStateProvider creates a new instance of StateProvider. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
func NewStateProvider(t testing.TB) *StateProvider {
mock := &StateProvider{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
+2 -1
View File
@@ -29,9 +29,10 @@ func (_m *Source) Now() time.Time {
return r0
}
// NewSource creates a new instance of Source. It also registers a cleanup function to assert the mocks expectations.
// NewSource creates a new instance of Source. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
func NewSource(t testing.TB) *Source {
mock := &Source{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
+2 -1
View File
@@ -68,9 +68,10 @@ func (_m *Provider) ReportEvidence(_a0 context.Context, _a1 types.Evidence) erro
return r0
}
// NewProvider creates a new instance of Provider. It also registers a cleanup function to assert the mocks expectations.
// NewProvider creates a new instance of Provider. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
func NewProvider(t testing.TB) *Provider {
mock := &Provider{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
+2 -1
View File
@@ -118,9 +118,10 @@ func (_m *LightClient) VerifyLightBlockAtHeight(ctx context.Context, height int6
return r0, r1
}
// NewLightClient creates a new instance of LightClient. It also registers a cleanup function to assert the mocks expectations.
// NewLightClient creates a new instance of LightClient. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
func NewLightClient(t testing.TB) *LightClient {
mock := &LightClient{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
+39 -13
View File
@@ -25,7 +25,12 @@ var (
)
func (a ABCIApp) ABCIInfo(ctx context.Context) (*coretypes.ResultABCIInfo, error) {
return &coretypes.ResultABCIInfo{Response: a.App.Info(ctx, proxy.RequestInfo)}, nil
res, err := a.App.Info(ctx, proxy.RequestInfo)
if err != nil {
return nil, err
}
return &coretypes.ResultABCIInfo{Response: *res}, nil
}
func (a ABCIApp) ABCIQuery(ctx context.Context, path string, data bytes.HexBytes) (*coretypes.ResultABCIQuery, error) {
@@ -33,35 +38,52 @@ func (a ABCIApp) ABCIQuery(ctx context.Context, path string, data bytes.HexBytes
}
func (a ABCIApp) ABCIQueryWithOptions(ctx context.Context, path string, data bytes.HexBytes, opts client.ABCIQueryOptions) (*coretypes.ResultABCIQuery, error) {
q := a.App.Query(ctx, abci.RequestQuery{
q, err := a.App.Query(ctx, abci.RequestQuery{
Data: data,
Path: path,
Height: opts.Height,
Prove: opts.Prove,
})
return &coretypes.ResultABCIQuery{Response: q}, nil
if err != nil {
return nil, err
}
return &coretypes.ResultABCIQuery{Response: *q}, nil
}
// NOTE: Caller should call a.App.Commit() separately,
// this function does not actually wait for a commit.
// TODO: Make it wait for a commit and set res.Height appropriately.
func (a ABCIApp) BroadcastTxCommit(ctx context.Context, tx types.Tx) (*coretypes.ResultBroadcastTxCommit, error) {
res := coretypes.ResultBroadcastTxCommit{}
res.CheckTx = a.App.CheckTx(ctx, abci.RequestCheckTx{Tx: tx})
if res.CheckTx.IsErr() {
return &res, nil
resp, err := a.App.CheckTx(ctx, abci.RequestCheckTx{Tx: tx})
if err != nil {
return nil, err
}
fb := a.App.FinalizeBlock(ctx, abci.RequestFinalizeBlock{Txs: [][]byte{tx}})
res := &coretypes.ResultBroadcastTxCommit{CheckTx: *resp}
if res.CheckTx.IsErr() {
return res, nil
}
fb, err := a.App.FinalizeBlock(ctx, abci.RequestFinalizeBlock{Txs: [][]byte{tx}})
if err != nil {
return nil, err
}
res.TxResult = *fb.TxResults[0]
res.Height = -1 // TODO
return &res, nil
return res, nil
}
func (a ABCIApp) BroadcastTxAsync(ctx context.Context, tx types.Tx) (*coretypes.ResultBroadcastTx, error) {
c := a.App.CheckTx(ctx, abci.RequestCheckTx{Tx: tx})
c, err := a.App.CheckTx(ctx, abci.RequestCheckTx{Tx: tx})
if err != nil {
return nil, err
}
// and this gets written in a background thread...
if !c.IsErr() {
go func() { a.App.FinalizeBlock(ctx, abci.RequestFinalizeBlock{Txs: [][]byte{tx}}) }()
go func() { _, _ = a.App.FinalizeBlock(ctx, abci.RequestFinalizeBlock{Txs: [][]byte{tx}}) }()
}
return &coretypes.ResultBroadcastTx{
Code: c.Code,
@@ -73,10 +95,14 @@ func (a ABCIApp) BroadcastTxAsync(ctx context.Context, tx types.Tx) (*coretypes.
}
func (a ABCIApp) BroadcastTxSync(ctx context.Context, tx types.Tx) (*coretypes.ResultBroadcastTx, error) {
c := a.App.CheckTx(ctx, abci.RequestCheckTx{Tx: tx})
c, err := a.App.CheckTx(ctx, abci.RequestCheckTx{Tx: tx})
if err != nil {
return nil, err
}
// and this gets written in a background thread...
if !c.IsErr() {
go func() { a.App.FinalizeBlock(ctx, abci.RequestFinalizeBlock{Txs: [][]byte{tx}}) }()
go func() { _, _ = a.App.FinalizeBlock(ctx, abci.RequestFinalizeBlock{Txs: [][]byte{tx}}) }()
}
return &coretypes.ResultBroadcastTx{
Code: c.Code,
+2 -1
View File
@@ -185,7 +185,8 @@ func TestABCIApp(t *testing.T) {
// commit
// TODO: This may not be necessary in the future
if res.Height == -1 {
m.App.Commit(ctx)
_, err := m.App.Commit(ctx)
require.NoError(t, err)
}
// check the key
+2 -1
View File
@@ -798,9 +798,10 @@ func (_m *Client) Validators(ctx context.Context, height *int64, page *int, perP
return r0, r1
}
// NewClient creates a new instance of Client. It also registers a cleanup function to assert the mocks expectations.
// NewClient creates a new instance of Client. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
func NewClient(t testing.TB) *Client {
mock := &Client{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
+14 -34
View File
@@ -13,35 +13,11 @@ replication engine. When run within the same process, Tendermint will call the A
application methods directly as Go method calls.
When Tendermint and the ABCI application are run as separate processes, Tendermint
opens four connections to the application for ABCI methods. The connections each
handle a subset of the ABCI method calls. These subsets are defined as follows:
opens maintains a connection over either a native socket protocol or
gRPC.
#### **Consensus** connection
* Driven by a consensus protocol and is responsible for block execution.
* Handles the `InitChain`, `BeginBlock`, `DeliverTx`, `EndBlock`, and `Commit` method
calls.
#### **Mempool** connection
* For validating new transactions, before they're shared or included in a block.
* Handles the `CheckTx` calls.
#### **Info** connection
* For initialization and for queries from the user.
* Handles the `Info` and `Query` calls.
#### **Snapshot** connection
* For serving and restoring [state sync snapshots](apps.md#state-sync).
* Handles the `ListSnapshots`, `LoadSnapshotChunk`, `OfferSnapshot`, and `ApplySnapshotChunk` calls.
Additionally, there is a `Flush` method that is called on every connection,
and an `Echo` method that is just for debugging.
More details on managing state across connections can be found in the section on
[ABCI Applications](apps.md).
More details on managing state across connections can be found in the
section on [ABCI Applications](apps.md).
## Errors
@@ -54,13 +30,17 @@ These methods also return a `Codespace` string to Tendermint. This field is
used to disambiguate `Code` values returned by different domains of the
application. The `Codespace` is a namespace for the `Code`.
The `Echo`, `Info`, `InitChain`, `BeginBlock`, `EndBlock`, `Commit` methods
do not return errors. An error in any of these methods represents a critical
issue that Tendermint has no reasonable way to handle. If there is an error in one
of these methods, the application must crash to ensure that the error is safely
handled by an operator.
The handling of non-zero response codes by Tendermint is described
below.
The handling of non-zero response codes by Tendermint is described below
Applications should always terminate if they encounter an issue in a
method where continuing would corrupt their own state, or for which
tendermint should not continue.
In the Go implementation these methods take a context and may return
an error. The context exists so that applications can terminate
gracefully during shutdown, and the error return value makes it
possible for applications to singal transient errors to Tendermint.
### CheckTx
+48 -48
View File
@@ -114,20 +114,20 @@ func NewApplication(cfg *Config) (*Application, error) {
}
// Info implements ABCI.
func (app *Application) Info(_ context.Context, req abci.RequestInfo) abci.ResponseInfo {
func (app *Application) Info(_ context.Context, req abci.RequestInfo) (*abci.ResponseInfo, error) {
app.mu.Lock()
defer app.mu.Unlock()
return abci.ResponseInfo{
return &abci.ResponseInfo{
Version: version.ABCIVersion,
AppVersion: 1,
LastBlockHeight: int64(app.state.Height),
LastBlockAppHash: app.state.Hash,
}
}, nil
}
// Info implements ABCI.
func (app *Application) InitChain(_ context.Context, req abci.RequestInitChain) abci.ResponseInitChain {
func (app *Application) InitChain(_ context.Context, req abci.RequestInitChain) (*abci.ResponseInitChain, error) {
app.mu.Lock()
defer app.mu.Unlock()
@@ -139,7 +139,7 @@ func (app *Application) InitChain(_ context.Context, req abci.RequestInitChain)
panic(err)
}
}
resp := abci.ResponseInitChain{
resp := &abci.ResponseInitChain{
AppHash: app.state.Hash,
ConsensusParams: &types.ConsensusParams{
Version: &types.VersionParams{
@@ -150,26 +150,26 @@ func (app *Application) InitChain(_ context.Context, req abci.RequestInitChain)
if resp.Validators, err = app.validatorUpdates(0); err != nil {
panic(err)
}
return resp
return resp, nil
}
// CheckTx implements ABCI.
func (app *Application) CheckTx(_ context.Context, req abci.RequestCheckTx) abci.ResponseCheckTx {
func (app *Application) CheckTx(_ context.Context, req abci.RequestCheckTx) (*abci.ResponseCheckTx, error) {
app.mu.Lock()
defer app.mu.Unlock()
_, _, err := parseTx(req.Tx)
if err != nil {
return abci.ResponseCheckTx{
return &abci.ResponseCheckTx{
Code: code.CodeTypeEncodingError,
Log: err.Error(),
}
}, nil
}
return abci.ResponseCheckTx{Code: code.CodeTypeOK, GasWanted: 1}
return &abci.ResponseCheckTx{Code: code.CodeTypeOK, GasWanted: 1}, nil
}
// FinalizeBlock implements ABCI.
func (app *Application) FinalizeBlock(_ context.Context, req abci.RequestFinalizeBlock) abci.ResponseFinalizeBlock {
func (app *Application) FinalizeBlock(_ context.Context, req abci.RequestFinalizeBlock) (*abci.ResponseFinalizeBlock, error) {
var txs = make([]*abci.ExecTxResult, len(req.Txs))
app.mu.Lock()
@@ -190,7 +190,7 @@ func (app *Application) FinalizeBlock(_ context.Context, req abci.RequestFinaliz
panic(err)
}
return abci.ResponseFinalizeBlock{
return &abci.ResponseFinalizeBlock{
TxResults: txs,
ValidatorUpdates: valUpdates,
Events: []abci.Event{
@@ -208,11 +208,11 @@ func (app *Application) FinalizeBlock(_ context.Context, req abci.RequestFinaliz
},
},
},
}
}, nil
}
// Commit implements ABCI.
func (app *Application) Commit(_ context.Context) abci.ResponseCommit {
func (app *Application) Commit(_ context.Context) (*abci.ResponseCommit, error) {
app.mu.Lock()
defer app.mu.Unlock()
@@ -235,26 +235,26 @@ func (app *Application) Commit(_ context.Context) abci.ResponseCommit {
if app.cfg.RetainBlocks > 0 {
retainHeight = int64(height - app.cfg.RetainBlocks + 1)
}
return abci.ResponseCommit{
return &abci.ResponseCommit{
Data: hash,
RetainHeight: retainHeight,
}
}, nil
}
// Query implements ABCI.
func (app *Application) Query(_ context.Context, req abci.RequestQuery) abci.ResponseQuery {
func (app *Application) Query(_ context.Context, req abci.RequestQuery) (*abci.ResponseQuery, error) {
app.mu.Lock()
defer app.mu.Unlock()
return abci.ResponseQuery{
return &abci.ResponseQuery{
Height: int64(app.state.Height),
Key: req.Data,
Value: []byte(app.state.Get(string(req.Data))),
}
}, nil
}
// ListSnapshots implements ABCI.
func (app *Application) ListSnapshots(_ context.Context, req abci.RequestListSnapshots) abci.ResponseListSnapshots {
func (app *Application) ListSnapshots(_ context.Context, req abci.RequestListSnapshots) (*abci.ResponseListSnapshots, error) {
app.mu.Lock()
defer app.mu.Unlock()
@@ -262,11 +262,11 @@ func (app *Application) ListSnapshots(_ context.Context, req abci.RequestListSna
if err != nil {
panic(err)
}
return abci.ResponseListSnapshots{Snapshots: snapshots}
return &abci.ResponseListSnapshots{Snapshots: snapshots}, nil
}
// LoadSnapshotChunk implements ABCI.
func (app *Application) LoadSnapshotChunk(_ context.Context, req abci.RequestLoadSnapshotChunk) abci.ResponseLoadSnapshotChunk {
func (app *Application) LoadSnapshotChunk(_ context.Context, req abci.RequestLoadSnapshotChunk) (*abci.ResponseLoadSnapshotChunk, error) {
app.mu.Lock()
defer app.mu.Unlock()
@@ -274,11 +274,11 @@ func (app *Application) LoadSnapshotChunk(_ context.Context, req abci.RequestLoa
if err != nil {
panic(err)
}
return abci.ResponseLoadSnapshotChunk{Chunk: chunk}
return &abci.ResponseLoadSnapshotChunk{Chunk: chunk}, nil
}
// OfferSnapshot implements ABCI.
func (app *Application) OfferSnapshot(_ context.Context, req abci.RequestOfferSnapshot) abci.ResponseOfferSnapshot {
func (app *Application) OfferSnapshot(_ context.Context, req abci.RequestOfferSnapshot) (*abci.ResponseOfferSnapshot, error) {
app.mu.Lock()
defer app.mu.Unlock()
@@ -287,11 +287,11 @@ func (app *Application) OfferSnapshot(_ context.Context, req abci.RequestOfferSn
}
app.restoreSnapshot = req.Snapshot
app.restoreChunks = [][]byte{}
return abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_ACCEPT}
return &abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_ACCEPT}, nil
}
// ApplySnapshotChunk implements ABCI.
func (app *Application) ApplySnapshotChunk(_ context.Context, req abci.RequestApplySnapshotChunk) abci.ResponseApplySnapshotChunk {
func (app *Application) ApplySnapshotChunk(_ context.Context, req abci.RequestApplySnapshotChunk) (*abci.ResponseApplySnapshotChunk, error) {
app.mu.Lock()
defer app.mu.Unlock()
@@ -311,7 +311,7 @@ func (app *Application) ApplySnapshotChunk(_ context.Context, req abci.RequestAp
app.restoreSnapshot = nil
app.restoreChunks = nil
}
return abci.ResponseApplySnapshotChunk{Result: abci.ResponseApplySnapshotChunk_ACCEPT}
return &abci.ResponseApplySnapshotChunk{Result: abci.ResponseApplySnapshotChunk_ACCEPT}, nil
}
// PrepareProposal will take the given transactions and attempt to prepare a
@@ -324,7 +324,7 @@ func (app *Application) ApplySnapshotChunk(_ context.Context, req abci.RequestAp
// If adding a special vote extension-generated transaction would cause the
// total number of transaction bytes to exceed `req.MaxTxBytes`, we will not
// append our special vote extension transaction.
func (app *Application) PrepareProposal(_ context.Context, req abci.RequestPrepareProposal) abci.ResponsePrepareProposal {
func (app *Application) PrepareProposal(_ context.Context, req abci.RequestPrepareProposal) (*abci.ResponsePrepareProposal, error) {
var sum int64
var extCount int
for _, vote := range req.LocalLastCommit.Votes {
@@ -378,9 +378,9 @@ func (app *Application) PrepareProposal(_ context.Context, req abci.RequestPrepa
"extTxLen", len(extTx),
)
}
return abci.ResponsePrepareProposal{
return &abci.ResponsePrepareProposal{
TxRecords: txRecords,
}
}, nil
}
// None of the transactions are modified by this application.
trs := make([]*abci.TxRecord, 0, len(req.Txs))
@@ -395,28 +395,28 @@ func (app *Application) PrepareProposal(_ context.Context, req abci.RequestPrepa
Tx: tx,
})
}
return abci.ResponsePrepareProposal{TxRecords: trs}
return &abci.ResponsePrepareProposal{TxRecords: trs}, nil
}
// ProcessProposal implements part of the Application interface.
// It accepts any proposal that does not contain a malformed transaction.
func (app *Application) ProcessProposal(_ context.Context, req abci.RequestProcessProposal) abci.ResponseProcessProposal {
func (app *Application) ProcessProposal(_ context.Context, req abci.RequestProcessProposal) (*abci.ResponseProcessProposal, error) {
for _, tx := range req.Txs {
k, v, err := parseTx(tx)
if err != nil {
app.logger.Error("malformed transaction in ProcessProposal", "tx", tx, "err", err)
return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}
return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil
}
// Additional check for vote extension-related txs
if k == voteExtensionKey {
_, err := strconv.Atoi(v)
if err != nil {
app.logger.Error("malformed vote extension transaction", k, v, "err", err)
return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}
return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil
}
}
}
return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}
return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil
}
// ExtendVote will produce vote extensions in the form of random numbers to
@@ -426,7 +426,7 @@ func (app *Application) ProcessProposal(_ context.Context, req abci.RequestProce
// a new transaction will be proposed that updates a special value in the
// key/value store ("extensionSum") with the sum of all of the numbers collected
// from the vote extensions.
func (app *Application) ExtendVote(_ context.Context, req abci.RequestExtendVote) abci.ResponseExtendVote {
func (app *Application) ExtendVote(_ context.Context, req abci.RequestExtendVote) (*abci.ResponseExtendVote, error) {
// We ignore any requests for vote extensions that don't match our expected
// next height.
if req.Height != int64(app.state.Height)+1 {
@@ -435,7 +435,7 @@ func (app *Application) ExtendVote(_ context.Context, req abci.RequestExtendVote
"expectedHeight", app.state.Height+1,
"requestHeight", req.Height,
)
return abci.ResponseExtendVote{}
return &abci.ResponseExtendVote{}, nil
}
ext := make([]byte, binary.MaxVarintLen64)
// We don't care that these values are generated by a weak random number
@@ -444,20 +444,20 @@ func (app *Application) ExtendVote(_ context.Context, req abci.RequestExtendVote
num := rand.Int63n(voteExtensionMaxVal)
extLen := binary.PutVarint(ext, num)
app.logger.Info("generated vote extension", "num", num, "ext", fmt.Sprintf("%x", ext[:extLen]), "state.Height", app.state.Height)
return abci.ResponseExtendVote{
return &abci.ResponseExtendVote{
VoteExtension: ext[:extLen],
}
}, nil
}
// VerifyVoteExtension simply validates vote extensions from other validators
// without doing anything about them. In this case, it just makes sure that the
// vote extension is a well-formed integer value.
func (app *Application) VerifyVoteExtension(_ context.Context, req abci.RequestVerifyVoteExtension) abci.ResponseVerifyVoteExtension {
func (app *Application) VerifyVoteExtension(_ context.Context, req abci.RequestVerifyVoteExtension) (*abci.ResponseVerifyVoteExtension, error) {
// We allow vote extensions to be optional
if len(req.VoteExtension) == 0 {
return abci.ResponseVerifyVoteExtension{
return &abci.ResponseVerifyVoteExtension{
Status: abci.ResponseVerifyVoteExtension_ACCEPT,
}
}, nil
}
if req.Height != int64(app.state.Height)+1 {
app.logger.Error(
@@ -465,22 +465,22 @@ func (app *Application) VerifyVoteExtension(_ context.Context, req abci.RequestV
"expectedHeight", app.state.Height,
"requestHeight", req.Height,
)
return abci.ResponseVerifyVoteExtension{
return &abci.ResponseVerifyVoteExtension{
Status: abci.ResponseVerifyVoteExtension_REJECT,
}
}, nil
}
num, err := parseVoteExtension(req.VoteExtension)
if err != nil {
app.logger.Error("failed to verify vote extension", "req", req, "err", err)
return abci.ResponseVerifyVoteExtension{
return &abci.ResponseVerifyVoteExtension{
Status: abci.ResponseVerifyVoteExtension_REJECT,
}
}, nil
}
app.logger.Info("verified vote extension value", "req", req, "num", num)
return abci.ResponseVerifyVoteExtension{
return &abci.ResponseVerifyVoteExtension{
Status: abci.ResponseVerifyVoteExtension_ACCEPT,
}
}, nil
}
func (app *Application) Rollback() error {