fix(baseapp): audit changes (#16596)
Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>
This commit is contained in:
parent
1afeca75a1
commit
b93081de05
@ -75,6 +75,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
* [#16547](https://github.com/cosmos/cosmos-sdk/pull/16547) Ensure a transaction's gas limit cannot exceed the block gas limit.
|
||||
* (x/auth/types) [#16554](https://github.com/cosmos/cosmos-sdk/pull/16554) `ModuleAccount.Validate` now reports a nil `.BaseAccount` instead of panicking.
|
||||
* (baseapp) [#16613](https://github.com/cosmos/cosmos-sdk/pull/16613) Ensure each message in a transaction has a registered handler, otherwise `CheckTx` will fail.
|
||||
* (baseapp) [#16596](https://github.com/cosmos/cosmos-sdk/pull/16596) Return error during ExtendVote and VerifyVoteExtension if the request height is earlier than `VoteExtensionsEnableHeight`.
|
||||
* (x/consensus) [#16713](https://github.com/cosmos/cosmos-sdk/pull/16713) Add missing ABCI param in MsgUpdateParams.
|
||||
* [#16639](https://github.com/cosmos/cosmos-sdk/pull/16639) Make sure we don't execute blocks beyond the halt height.
|
||||
* (baseapp) [#16700](https://github.com/cosmos/cosmos-sdk/pull/16700) Fix: Consensus Failure in returning no response to malformed transactions
|
||||
|
||||
15
UPGRADING.md
15
UPGRADING.md
@ -29,6 +29,21 @@ Additionally, the SDK is starting its abstraction from CometBFT Go types thoroug
|
||||
* The usage of CometBFT have been replaced to use the Cosmos SDK logger interface (`cosmossdk.io/log.Logger`).
|
||||
* The usage of `github.com/cometbft/cometbft/libs/bytes.HexByte` have been replaced by `[]byte`.
|
||||
|
||||
#### Enable Vote Extensions
|
||||
|
||||
:::tip This is an optional feature that is disabled by default.
|
||||
|
||||
Once all the code changes required to implement Vote Extensions are in place,
|
||||
they can be enabled by setting the consensus param `Abci.VoteExtensionsEnableHeight`
|
||||
to a value greater than zero.
|
||||
|
||||
In a new chain, this can be done in the `genesis.json` file.
|
||||
|
||||
For existing chains this can be done in two ways:
|
||||
|
||||
- During an upgrade the value is set in an upgrade handler.
|
||||
- A governance proposal that changes the consensus param **after a coordinated upgrade has taken place**.
|
||||
|
||||
### BaseApp
|
||||
|
||||
All ABCI methods now accept a pointer to the request and response types defined
|
||||
|
||||
@ -556,7 +556,9 @@ func (app *BaseApp) ExtendVote(_ context.Context, req *abci.RequestExtendVote) (
|
||||
// If vote extensions are not enabled, as a safety precaution, we return an
|
||||
// error.
|
||||
cp := app.GetConsensusParams(app.voteExtensionState.ctx)
|
||||
if cp.Abci != nil && cp.Abci.VoteExtensionsEnableHeight <= 0 {
|
||||
|
||||
extsEnabled := cp.Abci != nil && req.Height >= cp.Abci.VoteExtensionsEnableHeight && cp.Abci.VoteExtensionsEnableHeight != 0
|
||||
if !extsEnabled {
|
||||
return nil, fmt.Errorf("vote extensions are not enabled; unexpected call to ExtendVote at height %d", req.Height)
|
||||
}
|
||||
|
||||
@ -569,6 +571,7 @@ func (app *BaseApp) ExtendVote(_ context.Context, req *abci.RequestExtendVote) (
|
||||
WithHeaderInfo(coreheader.Info{
|
||||
ChainID: app.chainID,
|
||||
Height: req.Height,
|
||||
Hash: req.Hash,
|
||||
})
|
||||
|
||||
// add a deferred recover handler in case extendVote panics
|
||||
@ -607,7 +610,9 @@ func (app *BaseApp) VerifyVoteExtension(req *abci.RequestVerifyVoteExtension) (r
|
||||
// If vote extensions are not enabled, as a safety precaution, we return an
|
||||
// error.
|
||||
cp := app.GetConsensusParams(app.voteExtensionState.ctx)
|
||||
if cp.Abci != nil && cp.Abci.VoteExtensionsEnableHeight <= 0 {
|
||||
|
||||
extsEnabled := cp.Abci != nil && req.Height >= cp.Abci.VoteExtensionsEnableHeight && cp.Abci.VoteExtensionsEnableHeight != 0
|
||||
if !extsEnabled {
|
||||
return nil, fmt.Errorf("vote extensions are not enabled; unexpected call to VerifyVoteExtension at height %d", req.Height)
|
||||
}
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@ package baseapp_test
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
@ -11,13 +12,19 @@ import (
|
||||
"time"
|
||||
|
||||
abci "github.com/cometbft/cometbft/abci/types"
|
||||
"github.com/cometbft/cometbft/crypto/secp256k1"
|
||||
cmtprotocrypto "github.com/cometbft/cometbft/proto/tendermint/crypto"
|
||||
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
|
||||
dbm "github.com/cosmos/cosmos-db"
|
||||
protoio "github.com/cosmos/gogoproto/io"
|
||||
"github.com/cosmos/gogoproto/jsonpb"
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/math"
|
||||
pruningtypes "cosmossdk.io/store/pruning/types"
|
||||
"cosmossdk.io/store/snapshots"
|
||||
snapshottypes "cosmossdk.io/store/snapshots/types"
|
||||
@ -25,6 +32,7 @@ import (
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
baseapptestutil "github.com/cosmos/cosmos-sdk/baseapp/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/baseapp/testutil/mock"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
@ -51,12 +59,14 @@ func TestABCI_First_block_Height(t *testing.T) {
|
||||
suite := NewBaseAppSuite(t, baseapp.SetChainID("test-chain-id"))
|
||||
app := suite.baseApp
|
||||
|
||||
app.InitChain(&abci.RequestInitChain{
|
||||
_, err := app.InitChain(&abci.RequestInitChain{
|
||||
ChainId: "test-chain-id",
|
||||
ConsensusParams: &cmtproto.ConsensusParams{Block: &cmtproto.BlockParams{MaxGas: 5000000}},
|
||||
InitialHeight: 1,
|
||||
})
|
||||
app.Commit()
|
||||
require.NoError(t, err)
|
||||
_, err = app.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.GetContextForCheckTx(nil)
|
||||
require.Equal(t, int64(1), ctx.BlockHeight())
|
||||
@ -85,8 +95,8 @@ func TestABCI_InitChain(t *testing.T) {
|
||||
Data: key,
|
||||
}
|
||||
|
||||
// initChain is nil and chain ID is wrong - errors
|
||||
_, err := app.InitChain(&abci.RequestInitChain{ChainId: "wrong-chain-id"})
|
||||
// initChain is nil and chain ID is wrong - panics
|
||||
require.Error(t, err)
|
||||
|
||||
// initChain is nil - nothing happens
|
||||
@ -110,9 +120,12 @@ func TestABCI_InitChain(t *testing.T) {
|
||||
// The AppHash returned by a new chain is the sha256 hash of "".
|
||||
// $ echo -n '' | sha256sum
|
||||
// e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
apphash, err := hex.DecodeString("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(
|
||||
t,
|
||||
[]byte{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55},
|
||||
apphash,
|
||||
initChainRes.AppHash,
|
||||
)
|
||||
|
||||
@ -123,12 +136,15 @@ func TestABCI_InitChain(t *testing.T) {
|
||||
chainID = getCheckStateCtx(app).ChainID()
|
||||
require.Equal(t, "test-chain-id", chainID, "ChainID in checkState not set correctly in InitChain")
|
||||
|
||||
app.FinalizeBlock(&abci.RequestFinalizeBlock{
|
||||
_, err = app.FinalizeBlock(&abci.RequestFinalizeBlock{
|
||||
Hash: initChainRes.AppHash,
|
||||
Height: 1,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = app.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
app.Commit()
|
||||
resQ, err = app.Query(context.TODO(), &query)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(1), app.LastBlockHeight())
|
||||
@ -148,8 +164,10 @@ func TestABCI_InitChain(t *testing.T) {
|
||||
require.Equal(t, value, resQ.Value)
|
||||
|
||||
// commit and ensure we can still query
|
||||
app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: app.LastBlockHeight() + 1})
|
||||
app.Commit()
|
||||
_, err = app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: app.LastBlockHeight() + 1})
|
||||
require.NoError(t, err)
|
||||
_, err = app.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
resQ, err = app.Query(context.TODO(), &query)
|
||||
require.NoError(t, err)
|
||||
@ -161,12 +179,14 @@ func TestABCI_InitChain_WithInitialHeight(t *testing.T) {
|
||||
db := dbm.NewMemDB()
|
||||
app := baseapp.NewBaseApp(name, log.NewTestLogger(t), db, nil)
|
||||
|
||||
app.InitChain(
|
||||
_, err := app.InitChain(
|
||||
&abci.RequestInitChain{
|
||||
InitialHeight: 3,
|
||||
},
|
||||
)
|
||||
app.Commit()
|
||||
require.NoError(t, err)
|
||||
_, err = app.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, int64(3), app.LastBlockHeight())
|
||||
}
|
||||
@ -176,21 +196,172 @@ func TestABCI_FinalizeBlock_WithInitialHeight(t *testing.T) {
|
||||
db := dbm.NewMemDB()
|
||||
app := baseapp.NewBaseApp(name, log.NewTestLogger(t), db, nil)
|
||||
|
||||
app.InitChain(
|
||||
_, err := app.InitChain(
|
||||
&abci.RequestInitChain{
|
||||
InitialHeight: 3,
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err := app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 4})
|
||||
_, err = app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 4})
|
||||
require.Error(t, err, "invalid height: 4; expected: 3")
|
||||
|
||||
app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 3})
|
||||
app.Commit()
|
||||
_, err = app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 3})
|
||||
require.NoError(t, err)
|
||||
_, err = app.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, int64(3), app.LastBlockHeight())
|
||||
}
|
||||
|
||||
func TestABCI_FinalizeBlock_WithBeginAndEndBlocker(t *testing.T) {
|
||||
name := t.Name()
|
||||
db := dbm.NewMemDB()
|
||||
app := baseapp.NewBaseApp(name, log.NewTestLogger(t), db, nil)
|
||||
|
||||
app.SetBeginBlocker(func(ctx sdk.Context) (sdk.BeginBlock, error) {
|
||||
return sdk.BeginBlock{
|
||||
Events: []abci.Event{
|
||||
{
|
||||
Type: "sometype",
|
||||
Attributes: []abci.EventAttribute{
|
||||
{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
})
|
||||
|
||||
app.SetEndBlocker(func(ctx sdk.Context) (sdk.EndBlock, error) {
|
||||
return sdk.EndBlock{
|
||||
Events: []abci.Event{
|
||||
{
|
||||
Type: "anothertype",
|
||||
Attributes: []abci.EventAttribute{
|
||||
{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
})
|
||||
|
||||
_, err := app.InitChain(
|
||||
&abci.RequestInitChain{
|
||||
InitialHeight: 1,
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 1})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, res.Events, 2)
|
||||
|
||||
require.Equal(t, "sometype", res.Events[0].Type)
|
||||
require.Equal(t, "foo", res.Events[0].Attributes[0].Key)
|
||||
require.Equal(t, "bar", res.Events[0].Attributes[0].Value)
|
||||
require.Equal(t, "mode", res.Events[0].Attributes[1].Key)
|
||||
require.Equal(t, "BeginBlock", res.Events[0].Attributes[1].Value)
|
||||
|
||||
require.Equal(t, "anothertype", res.Events[1].Type)
|
||||
require.Equal(t, "foo", res.Events[1].Attributes[0].Key)
|
||||
require.Equal(t, "bar", res.Events[1].Attributes[0].Value)
|
||||
require.Equal(t, "mode", res.Events[1].Attributes[1].Key)
|
||||
require.Equal(t, "EndBlock", res.Events[1].Attributes[1].Value)
|
||||
|
||||
_, err = app.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, int64(1), app.LastBlockHeight())
|
||||
}
|
||||
|
||||
func TestABCI_ExtendVote(t *testing.T) {
|
||||
name := t.Name()
|
||||
db := dbm.NewMemDB()
|
||||
app := baseapp.NewBaseApp(name, log.NewTestLogger(t), db, nil)
|
||||
|
||||
app.SetExtendVoteHandler(func(ctx sdk.Context, req *abci.RequestExtendVote) (*abci.ResponseExtendVote, error) {
|
||||
voteExt := "foo" + hex.EncodeToString(req.Hash) + strconv.FormatInt(req.Height, 10)
|
||||
return &abci.ResponseExtendVote{VoteExtension: []byte(voteExt)}, nil
|
||||
})
|
||||
|
||||
app.SetVerifyVoteExtensionHandler(func(ctx sdk.Context, req *abci.RequestVerifyVoteExtension) (*abci.ResponseVerifyVoteExtension, error) {
|
||||
// do some kind of verification here
|
||||
expectedVoteExt := "foo" + hex.EncodeToString(req.Hash) + strconv.FormatInt(req.Height, 10)
|
||||
if !bytes.Equal(req.VoteExtension, []byte(expectedVoteExt)) {
|
||||
return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_REJECT}, nil
|
||||
}
|
||||
|
||||
return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_ACCEPT}, nil
|
||||
})
|
||||
|
||||
app.SetParamStore(¶mStore{db: dbm.NewMemDB()})
|
||||
_, err := app.InitChain(
|
||||
&abci.RequestInitChain{
|
||||
InitialHeight: 1,
|
||||
ConsensusParams: &cmtproto.ConsensusParams{
|
||||
Abci: &cmtproto.ABCIParams{
|
||||
VoteExtensionsEnableHeight: 200,
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Votes not enabled yet
|
||||
_, err = app.ExtendVote(context.Background(), &abci.RequestExtendVote{Height: 123, Hash: []byte("thehash")})
|
||||
require.ErrorContains(t, err, "vote extensions are not enabled")
|
||||
|
||||
// First vote on the first enabled height
|
||||
res, err := app.ExtendVote(context.Background(), &abci.RequestExtendVote{Height: 200, Hash: []byte("thehash")})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, res.VoteExtension, 20)
|
||||
|
||||
res, err = app.ExtendVote(context.Background(), &abci.RequestExtendVote{Height: 1000, Hash: []byte("thehash")})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, res.VoteExtension, 21)
|
||||
|
||||
// Error during vote extension should return an empty vote extension and no error
|
||||
app.SetExtendVoteHandler(func(ctx sdk.Context, req *abci.RequestExtendVote) (*abci.ResponseExtendVote, error) {
|
||||
return nil, errors.New("some error")
|
||||
})
|
||||
res, err = app.ExtendVote(context.Background(), &abci.RequestExtendVote{Height: 1000, Hash: []byte("thehash")})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, res.VoteExtension, 0)
|
||||
|
||||
// Verify Vote Extensions
|
||||
_, err = app.VerifyVoteExtension(&abci.RequestVerifyVoteExtension{Height: 123, VoteExtension: []byte("1234567")})
|
||||
require.ErrorContains(t, err, "vote extensions are not enabled")
|
||||
|
||||
// First vote on the first enabled height
|
||||
vres, err := app.VerifyVoteExtension(&abci.RequestVerifyVoteExtension{Height: 200, Hash: []byte("thehash"), VoteExtension: []byte("foo74686568617368200")})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, abci.ResponseVerifyVoteExtension_ACCEPT, vres.Status)
|
||||
|
||||
vres, err = app.VerifyVoteExtension(&abci.RequestVerifyVoteExtension{Height: 1000, Hash: []byte("thehash"), VoteExtension: []byte("foo746865686173681000")})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, abci.ResponseVerifyVoteExtension_ACCEPT, vres.Status)
|
||||
|
||||
// Reject because it's just some random bytes
|
||||
vres, err = app.VerifyVoteExtension(&abci.RequestVerifyVoteExtension{Height: 201, Hash: []byte("thehash"), VoteExtension: []byte("12345678")})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, abci.ResponseVerifyVoteExtension_REJECT, vres.Status)
|
||||
|
||||
// Reject because the verification failed (no error)
|
||||
app.SetVerifyVoteExtensionHandler(func(ctx sdk.Context, req *abci.RequestVerifyVoteExtension) (*abci.ResponseVerifyVoteExtension, error) {
|
||||
return nil, errors.New("some error")
|
||||
})
|
||||
vres, err = app.VerifyVoteExtension(&abci.RequestVerifyVoteExtension{Height: 201, Hash: []byte("thehash"), VoteExtension: []byte("12345678")})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, abci.ResponseVerifyVoteExtension_REJECT, vres.Status)
|
||||
}
|
||||
|
||||
func TestABCI_GRPCQuery(t *testing.T) {
|
||||
grpcQueryOpt := func(bapp *baseapp.BaseApp) {
|
||||
testdata.RegisterQueryServer(
|
||||
@ -201,9 +372,10 @@ func TestABCI_GRPCQuery(t *testing.T) {
|
||||
|
||||
suite := NewBaseAppSuite(t, grpcQueryOpt)
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
req := testdata.SayHelloRequest{Name: "foo"}
|
||||
reqBz, err := req.Marshal()
|
||||
@ -217,8 +389,10 @@ func TestABCI_GRPCQuery(t *testing.T) {
|
||||
require.Equal(t, sdkerrors.ErrInvalidHeight.ABCICode(), resQuery.Code, resQuery)
|
||||
require.Contains(t, resQuery.Log, "TestABCI_GRPCQuery is not ready; please wait for first block")
|
||||
|
||||
suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{Height: suite.baseApp.LastBlockHeight() + 1})
|
||||
suite.baseApp.Commit()
|
||||
_, err = suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{Height: suite.baseApp.LastBlockHeight() + 1})
|
||||
require.NoError(t, err)
|
||||
_, err = suite.baseApp.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
reqQuery := abci.RequestQuery{
|
||||
Data: reqBz,
|
||||
@ -279,9 +453,10 @@ func TestBaseApp_PrepareCheckState(t *testing.T) {
|
||||
|
||||
app := baseapp.NewBaseApp(name, logger, db, nil)
|
||||
app.SetParamStore(¶mStore{db: dbm.NewMemDB()})
|
||||
app.InitChain(&abci.RequestInitChain{
|
||||
_, err := app.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: cp,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
wasPrepareCheckStateCalled := false
|
||||
app.SetPrepareCheckStater(func(ctx sdk.Context) {
|
||||
@ -289,7 +464,8 @@ func TestBaseApp_PrepareCheckState(t *testing.T) {
|
||||
})
|
||||
app.Seal()
|
||||
|
||||
app.Commit()
|
||||
_, err = app.Commit()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, wasPrepareCheckStateCalled)
|
||||
}
|
||||
|
||||
@ -306,9 +482,10 @@ func TestBaseApp_Precommit(t *testing.T) {
|
||||
|
||||
app := baseapp.NewBaseApp(name, logger, db, nil)
|
||||
app.SetParamStore(¶mStore{db: dbm.NewMemDB()})
|
||||
app.InitChain(&abci.RequestInitChain{
|
||||
_, err := app.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: cp,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
wasPrecommiterCalled := false
|
||||
app.SetPrecommiter(func(ctx sdk.Context) {
|
||||
@ -316,7 +493,8 @@ func TestBaseApp_Precommit(t *testing.T) {
|
||||
})
|
||||
app.Seal()
|
||||
|
||||
app.Commit()
|
||||
_, err = app.Commit()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, wasPrecommiterCalled)
|
||||
}
|
||||
|
||||
@ -331,9 +509,10 @@ func TestABCI_CheckTx(t *testing.T) {
|
||||
baseapptestutil.RegisterCounterServer(suite.baseApp.MsgServiceRouter(), CounterServerImpl{t, capKey1, counterKey})
|
||||
|
||||
nTxs := int64(5)
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
for i := int64(0); i < nTxs; i++ {
|
||||
tx := newTxCounter(t, suite.txConfig, i, 0) // no messages
|
||||
@ -353,7 +532,7 @@ func TestABCI_CheckTx(t *testing.T) {
|
||||
require.Equal(t, nTxs, storedCounter)
|
||||
|
||||
// if a block is committed, CheckTx state should be reset
|
||||
_, err := suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{
|
||||
_, err = suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{
|
||||
Height: 1,
|
||||
Hash: []byte("hash"),
|
||||
})
|
||||
@ -362,7 +541,8 @@ func TestABCI_CheckTx(t *testing.T) {
|
||||
require.NotNil(t, getCheckStateCtx(suite.baseApp).BlockGasMeter(), "block gas meter should have been set to checkState")
|
||||
require.NotEmpty(t, getCheckStateCtx(suite.baseApp).HeaderHash())
|
||||
|
||||
suite.baseApp.Commit()
|
||||
_, err = suite.baseApp.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
checkStateStore = getCheckStateCtx(suite.baseApp).KVStore(capKey1)
|
||||
storedBytes := checkStateStore.Get(counterKey)
|
||||
@ -374,9 +554,10 @@ func TestABCI_FinalizeBlock_DeliverTx(t *testing.T) {
|
||||
anteOpt := func(bapp *baseapp.BaseApp) { bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, anteKey)) }
|
||||
suite := NewBaseAppSuite(t, anteOpt)
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
deliverKey := []byte("deliver-key")
|
||||
baseapptestutil.RegisterCounterServer(suite.baseApp.MsgServiceRouter(), CounterServerImpl{t, capKey1, deliverKey})
|
||||
@ -413,7 +594,8 @@ func TestABCI_FinalizeBlock_DeliverTx(t *testing.T) {
|
||||
require.Equal(t, sdk.MarkEventsToIndex(counterEvent(sdk.EventTypeMessage, counter).ToABCIEvents(), map[string]struct{}{})[0].Attributes[0], events[2].Attributes[0], "msg handler update counter event")
|
||||
}
|
||||
|
||||
suite.baseApp.Commit()
|
||||
_, err = suite.baseApp.Commit()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -422,9 +604,10 @@ func TestABCI_FinalizeBlock_MultiMsg(t *testing.T) {
|
||||
anteOpt := func(bapp *baseapp.BaseApp) { bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, anteKey)) }
|
||||
suite := NewBaseAppSuite(t, anteOpt)
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
deliverKey := []byte("deliver-key")
|
||||
baseapptestutil.RegisterCounterServer(suite.baseApp.MsgServiceRouter(), CounterServerImpl{t, capKey1, deliverKey})
|
||||
@ -438,10 +621,11 @@ func TestABCI_FinalizeBlock_MultiMsg(t *testing.T) {
|
||||
txBytes, err := suite.txConfig.TxEncoder()(tx)
|
||||
require.NoError(t, err)
|
||||
|
||||
suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{
|
||||
_, err = suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{
|
||||
Height: 1,
|
||||
Txs: [][]byte{txBytes},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
store := getFinalizeBlockStateCtx(suite.baseApp).KVStore(capKey1)
|
||||
|
||||
@ -500,9 +684,10 @@ func TestABCI_Query_SimulateTx(t *testing.T) {
|
||||
}
|
||||
suite := NewBaseAppSuite(t, anteOpt)
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
baseapptestutil.RegisterCounterServer(suite.baseApp.MsgServiceRouter(), CounterServerImplGasMeterOnly{gasConsumed})
|
||||
|
||||
@ -544,8 +729,10 @@ func TestABCI_Query_SimulateTx(t *testing.T) {
|
||||
require.Equal(t, result.Events, simRes.Result.Events)
|
||||
require.True(t, bytes.Equal(result.Data, simRes.Result.Data))
|
||||
|
||||
suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{Height: count})
|
||||
suite.baseApp.Commit()
|
||||
_, err = suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{Height: count})
|
||||
require.NoError(t, err)
|
||||
_, err = suite.baseApp.Commit()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -559,13 +746,15 @@ func TestABCI_InvalidTransaction(t *testing.T) {
|
||||
suite := NewBaseAppSuite(t, anteOpt)
|
||||
baseapptestutil.RegisterCounterServer(suite.baseApp.MsgServiceRouter(), CounterServerImplGasMeterOnly{})
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{
|
||||
_, err = suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{
|
||||
Height: 1,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// malformed transaction bytes
|
||||
{
|
||||
@ -703,15 +892,18 @@ func TestABCI_TxGasLimits(t *testing.T) {
|
||||
suite := NewBaseAppSuite(t, anteOpt)
|
||||
baseapptestutil.RegisterCounterServer(suite.baseApp.MsgServiceRouter(), CounterServerImplGasMeterOnly{})
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{
|
||||
_, err = suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{
|
||||
Height: 1,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
suite.baseApp.Commit()
|
||||
_, err = suite.baseApp.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := []struct {
|
||||
tx signing.Tx
|
||||
@ -792,15 +984,17 @@ func TestABCI_MaxBlockGasLimits(t *testing.T) {
|
||||
suite := NewBaseAppSuite(t, anteOpt)
|
||||
baseapptestutil.RegisterCounterServer(suite.baseApp.MsgServiceRouter(), CounterServerImplGasMeterOnly{})
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{
|
||||
Block: &cmtproto.BlockParams{
|
||||
MaxGas: 100,
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 1})
|
||||
_, err = suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 1})
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := []struct {
|
||||
tx signing.Tx
|
||||
@ -825,7 +1019,8 @@ func TestABCI_MaxBlockGasLimits(t *testing.T) {
|
||||
tx := tc.tx
|
||||
|
||||
// reset block gas
|
||||
suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{Height: suite.baseApp.LastBlockHeight() + 1})
|
||||
_, err = suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{Height: suite.baseApp.LastBlockHeight() + 1})
|
||||
require.NoError(t, err)
|
||||
|
||||
// execute the transaction multiple times
|
||||
for j := 0; j < tc.numDelivers; j++ {
|
||||
@ -890,13 +1085,14 @@ func TestABCI_GasConsumptionBadTx(t *testing.T) {
|
||||
suite := NewBaseAppSuite(t, anteOpt)
|
||||
baseapptestutil.RegisterCounterServer(suite.baseApp.MsgServiceRouter(), CounterServerImplGasMeterOnly{})
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{
|
||||
Block: &cmtproto.BlockParams{
|
||||
MaxGas: 9,
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
tx := newTxCounter(t, suite.txConfig, 5, 0)
|
||||
tx = setFailOnAnte(t, suite.txConfig, tx, true)
|
||||
@ -928,9 +1124,10 @@ func TestABCI_Query(t *testing.T) {
|
||||
suite := NewBaseAppSuite(t, anteOpt)
|
||||
baseapptestutil.RegisterCounterServer(suite.baseApp.MsgServiceRouter(), CounterServerImplGasMeterOnly{})
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// NOTE: "/store/key1" tells us KVStore
|
||||
// and the final "/key" says to use the data as the
|
||||
@ -958,7 +1155,7 @@ func TestABCI_Query(t *testing.T) {
|
||||
bz, err := suite.txConfig.TxEncoder()(tx)
|
||||
require.NoError(t, err)
|
||||
|
||||
suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{
|
||||
_, err = suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{
|
||||
Height: 1,
|
||||
Txs: [][]byte{bz},
|
||||
})
|
||||
@ -969,7 +1166,8 @@ func TestABCI_Query(t *testing.T) {
|
||||
require.Equal(t, 0, len(res.Value))
|
||||
|
||||
// query returns correct value after Commit
|
||||
suite.baseApp.Commit()
|
||||
_, err = suite.baseApp.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err = suite.baseApp.Query(context.TODO(), &query)
|
||||
require.NoError(t, err)
|
||||
@ -1071,13 +1269,14 @@ func TestABCI_GetBlockRetentionHeight(t *testing.T) {
|
||||
tc := tc
|
||||
|
||||
tc.bapp.SetParamStore(¶mStore{db: dbm.NewMemDB()})
|
||||
tc.bapp.InitChain(&abci.RequestInitChain{
|
||||
_, err = tc.bapp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{
|
||||
Evidence: &cmtproto.EvidenceParams{
|
||||
MaxAgeNumBlocks: tc.maxAgeBlocks,
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run(name, func(t *testing.T) {
|
||||
require.Equal(t, tc.expected, tc.bapp.GetBlockRetentionHeight(tc.commitHeight))
|
||||
@ -1100,8 +1299,10 @@ func TestPrepareCheckStateCalledWithCheckState(t *testing.T) {
|
||||
wasPrepareCheckStateCalled = true
|
||||
})
|
||||
|
||||
app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 1})
|
||||
app.Commit()
|
||||
_, err := app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 1})
|
||||
require.NoError(t, err)
|
||||
_, err = app.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, true, wasPrepareCheckStateCalled)
|
||||
}
|
||||
@ -1122,8 +1323,10 @@ func TestPrecommiterCalledWithDeliverState(t *testing.T) {
|
||||
wasPrecommiterCalled = true
|
||||
})
|
||||
|
||||
app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 1})
|
||||
app.Commit()
|
||||
_, err := app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 1})
|
||||
require.NoError(t, err)
|
||||
_, err = app.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, true, wasPrecommiterCalled)
|
||||
}
|
||||
@ -1139,9 +1342,10 @@ func TestABCI_Proposal_HappyPath(t *testing.T) {
|
||||
baseapptestutil.RegisterKeyValueServer(suite.baseApp.MsgServiceRouter(), MsgKeyValueImpl{})
|
||||
baseapptestutil.RegisterCounterServer(suite.baseApp.MsgServiceRouter(), NoopCounterServerImpl{})
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
tx := newTxCounter(t, suite.txConfig, 0, 1)
|
||||
txBytes, err := suite.txConfig.TxEncoder()(tx)
|
||||
@ -1183,13 +1387,14 @@ func TestABCI_Proposal_HappyPath(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, abci.ResponseProcessProposal_ACCEPT, resProcessProposal.Status)
|
||||
|
||||
// the same txs as in PrepareProposal
|
||||
res, err := suite.baseApp.FinalizeBlock(&abci.RequestFinalizeBlock{
|
||||
Height: suite.baseApp.LastBlockHeight() + 1,
|
||||
Txs: [][]byte{txBytes},
|
||||
Txs: reqProposalTxBytes[:],
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, 1, pool.CountTx())
|
||||
require.Equal(t, 0, pool.CountTx())
|
||||
|
||||
require.NotEmpty(t, res.TxResults[0].Events)
|
||||
require.True(t, res.TxResults[0].IsOK(), fmt.Sprintf("%v", res))
|
||||
@ -1216,10 +1421,11 @@ func TestABCI_Proposal_Read_State_PrepareProposal(t *testing.T) {
|
||||
|
||||
suite := NewBaseAppSuite(t, setInitChainerOpt, prepareOpt)
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
InitialHeight: 1,
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
reqPrepareProposal := abci.RequestPrepareProposal{
|
||||
MaxTxBytes: 1000,
|
||||
@ -1238,10 +1444,6 @@ func TestABCI_Proposal_Read_State_PrepareProposal(t *testing.T) {
|
||||
resProcessProposal, err := suite.baseApp.ProcessProposal(&reqProcessProposal)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, abci.ResponseProcessProposal_ACCEPT, resProcessProposal.Status)
|
||||
|
||||
// suite.baseApp.BeginBlock(abci.RequestBeginBlock{
|
||||
// Header: cmtproto.Header{Height: suite.baseApp.LastBlockHeight() + 1},
|
||||
// })
|
||||
}
|
||||
|
||||
func TestABCI_Proposals_WithVE(t *testing.T) {
|
||||
@ -1317,9 +1519,10 @@ func TestABCI_PrepareProposal_ReachedMaxBytes(t *testing.T) {
|
||||
suite := NewBaseAppSuite(t, anteOpt, baseapp.SetMempool(pool))
|
||||
baseapptestutil.RegisterCounterServer(suite.baseApp.MsgServiceRouter(), NoopCounterServerImpl{})
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
tx2 := newTxCounter(t, suite.txConfig, int64(i), int64(i))
|
||||
@ -1346,12 +1549,13 @@ func TestABCI_PrepareProposal_BadEncoding(t *testing.T) {
|
||||
suite := NewBaseAppSuite(t, anteOpt, baseapp.SetMempool(pool))
|
||||
baseapptestutil.RegisterCounterServer(suite.baseApp.MsgServiceRouter(), NoopCounterServerImpl{})
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
tx := newTxCounter(t, suite.txConfig, 0, 0)
|
||||
err := pool.Insert(sdk.Context{}, tx)
|
||||
err = pool.Insert(sdk.Context{}, tx)
|
||||
require.NoError(t, err)
|
||||
|
||||
reqPrepareProposal := abci.RequestPrepareProposal{
|
||||
@ -1410,9 +1614,10 @@ func TestABCI_PrepareProposal_Failures(t *testing.T) {
|
||||
suite := NewBaseAppSuite(t, anteOpt, baseapp.SetMempool(pool))
|
||||
baseapptestutil.RegisterCounterServer(suite.baseApp.MsgServiceRouter(), NoopCounterServerImpl{})
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
tx := newTxCounter(t, suite.txConfig, 0, 0)
|
||||
txBytes, err := suite.txConfig.TxEncoder()(tx)
|
||||
@ -1450,9 +1655,10 @@ func TestABCI_PrepareProposal_PanicRecovery(t *testing.T) {
|
||||
}
|
||||
suite := NewBaseAppSuite(t, prepareOpt)
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
req := abci.RequestPrepareProposal{
|
||||
MaxTxBytes: 1000,
|
||||
@ -1466,6 +1672,119 @@ func TestABCI_PrepareProposal_PanicRecovery(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestABCI_PrepareProposal_VoteExtensions(t *testing.T) {
|
||||
// set up mocks
|
||||
ctrl := gomock.NewController(t)
|
||||
valStore := mock.NewMockValidatorStore(ctrl)
|
||||
privkey := secp256k1.GenPrivKey()
|
||||
pubkey := privkey.PubKey()
|
||||
addr := sdk.AccAddress(pubkey.Address())
|
||||
tmPk := cmtprotocrypto.PublicKey{
|
||||
Sum: &cmtprotocrypto.PublicKey_Secp256K1{
|
||||
Secp256K1: pubkey.Bytes(),
|
||||
},
|
||||
}
|
||||
|
||||
val1 := mock.NewMockValidator(ctrl)
|
||||
val1.EXPECT().BondedTokens().Return(math.NewInt(667))
|
||||
val1.EXPECT().CmtConsPublicKey().Return(tmPk, nil).AnyTimes()
|
||||
|
||||
consAddr := sdk.ConsAddress(addr.String())
|
||||
valStore.EXPECT().GetValidatorByConsAddr(gomock.Any(), consAddr.Bytes()).Return(val1, nil).AnyTimes()
|
||||
valStore.EXPECT().TotalBondedTokens(gomock.Any()).Return(math.NewInt(1000)).AnyTimes()
|
||||
|
||||
// set up baseapp
|
||||
prepareOpt := func(bapp *baseapp.BaseApp) {
|
||||
bapp.SetPrepareProposal(func(ctx sdk.Context, req *abci.RequestPrepareProposal) (*abci.ResponsePrepareProposal, error) {
|
||||
cp := ctx.ConsensusParams()
|
||||
extsEnabled := cp.Abci != nil && req.Height >= cp.Abci.VoteExtensionsEnableHeight && cp.Abci.VoteExtensionsEnableHeight != 0
|
||||
if extsEnabled {
|
||||
err := baseapp.ValidateVoteExtensions(ctx, valStore, req.Height, bapp.ChainID(), req.LocalLastCommit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Txs = append(req.Txs, []byte("some-tx-that-does-something-from-votes"))
|
||||
|
||||
}
|
||||
return &abci.ResponsePrepareProposal{Txs: req.Txs}, nil
|
||||
})
|
||||
}
|
||||
|
||||
suite := NewBaseAppSuite(t, prepareOpt)
|
||||
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
InitialHeight: 1,
|
||||
ConsensusParams: &cmtproto.ConsensusParams{
|
||||
Abci: &cmtproto.ABCIParams{
|
||||
VoteExtensionsEnableHeight: 2,
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// first test without vote extensions, no new txs should be added
|
||||
reqPrepareProposal := abci.RequestPrepareProposal{
|
||||
MaxTxBytes: 1000,
|
||||
Height: 1, // this value can't be 0
|
||||
}
|
||||
resPrepareProposal, err := suite.baseApp.PrepareProposal(&reqPrepareProposal)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(resPrepareProposal.Txs))
|
||||
|
||||
// now we try with vote extensions, a new tx should show up
|
||||
marshalDelimitedFn := func(msg proto.Message) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
if err := protoio.NewDelimitedWriter(&buf).WriteMsg(msg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
ext := []byte("something")
|
||||
cve := cmtproto.CanonicalVoteExtension{
|
||||
Extension: ext,
|
||||
Height: 2, // the vote extension was signed in the previous height
|
||||
Round: int64(0),
|
||||
ChainId: suite.baseApp.ChainID(),
|
||||
}
|
||||
|
||||
bz, err := marshalDelimitedFn(&cve)
|
||||
require.NoError(t, err)
|
||||
|
||||
extSig, err := privkey.Sign(bz)
|
||||
require.NoError(t, err)
|
||||
|
||||
reqPrepareProposal = abci.RequestPrepareProposal{
|
||||
MaxTxBytes: 1000,
|
||||
Height: 3, // this value can't be 0
|
||||
LocalLastCommit: abci.ExtendedCommitInfo{
|
||||
Round: 0,
|
||||
Votes: []abci.ExtendedVoteInfo{
|
||||
{
|
||||
Validator: abci.Validator{
|
||||
Address: consAddr.Bytes(),
|
||||
// this is being ignored by our validation function
|
||||
Power: sdk.TokensToConsensusPower(math.NewInt(1000000), sdk.DefaultPowerReduction),
|
||||
},
|
||||
VoteExtension: ext,
|
||||
ExtensionSignature: extSig,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
resPrepareProposal, err = suite.baseApp.PrepareProposal(&reqPrepareProposal)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(resPrepareProposal.Txs))
|
||||
|
||||
// now vote extensions but our sole voter doesn't reach majority
|
||||
val1.EXPECT().BondedTokens().Return(math.NewInt(666))
|
||||
resPrepareProposal, err = suite.baseApp.PrepareProposal(&reqPrepareProposal)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(resPrepareProposal.Txs))
|
||||
}
|
||||
|
||||
func TestABCI_ProcessProposal_PanicRecovery(t *testing.T) {
|
||||
processOpt := func(app *baseapp.BaseApp) {
|
||||
app.SetProcessProposal(func(ctx sdk.Context, rpp *abci.RequestProcessProposal) (*abci.ResponseProcessProposal, error) {
|
||||
@ -1474,9 +1793,10 @@ func TestABCI_ProcessProposal_PanicRecovery(t *testing.T) {
|
||||
}
|
||||
suite := NewBaseAppSuite(t, processOpt)
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotPanics(t, func() {
|
||||
res, err := suite.baseApp.ProcessProposal(&abci.RequestProcessProposal{Height: 1})
|
||||
@ -1512,9 +1832,10 @@ func TestABCI_Proposal_Reset_State_Between_Calls(t *testing.T) {
|
||||
|
||||
suite := NewBaseAppSuite(t, prepareOpt, processOpt)
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
reqPrepareProposal := abci.RequestPrepareProposal{
|
||||
MaxTxBytes: 1000,
|
||||
|
||||
@ -50,7 +50,7 @@ type (
|
||||
|
||||
// ValidateVoteExtensions defines a helper function for verifying vote extension
|
||||
// signatures that may be passed or manually injected into a block proposal from
|
||||
// a proposer in ProcessProposal. It returns an error if any signature is invalid
|
||||
// a proposer in PrepareProposal. It returns an error if any signature is invalid
|
||||
// or if unexpected vote extensions and/or signatures are found or less than 2/3
|
||||
// power is received.
|
||||
func ValidateVoteExtensions(
|
||||
@ -61,7 +61,7 @@ func ValidateVoteExtensions(
|
||||
extCommit abci.ExtendedCommitInfo,
|
||||
) error {
|
||||
cp := ctx.ConsensusParams()
|
||||
extsEnabled := cp.Abci != nil && cp.Abci.VoteExtensionsEnableHeight > 0
|
||||
extsEnabled := cp.Abci != nil && currentHeight >= cp.Abci.VoteExtensionsEnableHeight && cp.Abci.VoteExtensionsEnableHeight != 0
|
||||
|
||||
marshalDelimitedFn := func(msg proto.Message) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
@ -72,7 +72,7 @@ func ValidateVoteExtensions(
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
var sumVP math.Int
|
||||
sumVP := math.NewInt(0)
|
||||
for _, vote := range extCommit.Votes {
|
||||
if !extsEnabled {
|
||||
if len(vote.VoteExtension) > 0 {
|
||||
|
||||
@ -101,9 +101,10 @@ func NewBaseAppSuiteWithSnapshots(t *testing.T, cfg SnapshotsConfig, opts ...fun
|
||||
|
||||
baseapptestutil.RegisterKeyValueServer(suite.baseApp.MsgServiceRouter(), MsgKeyValueImpl{})
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err = suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
r := rand.New(rand.NewSource(3920758213583))
|
||||
keyCounter := 0
|
||||
@ -458,9 +459,10 @@ func TestCustomRunTxPanicHandler(t *testing.T) {
|
||||
suite := NewBaseAppSuite(t, anteOpt)
|
||||
baseapptestutil.RegisterCounterServer(suite.baseApp.MsgServiceRouter(), NoopCounterServerImpl{})
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
suite.baseApp.AddRunTxRecoveryHandler(func(recoveryObj interface{}) error {
|
||||
err, ok := recoveryObj.(error)
|
||||
@ -497,9 +499,10 @@ func TestBaseAppAnteHandler(t *testing.T) {
|
||||
deliverKey := []byte("deliver-key")
|
||||
baseapptestutil.RegisterCounterServer(suite.baseApp.MsgServiceRouter(), CounterServerImpl{t, capKey1, deliverKey})
|
||||
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{
|
||||
ConsensusParams: &cmtproto.ConsensusParams{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// execute a tx that will fail ante handler execution
|
||||
//
|
||||
@ -569,11 +572,15 @@ func TestABCI_CreateQueryContext(t *testing.T) {
|
||||
name := t.Name()
|
||||
app := baseapp.NewBaseApp(name, log.NewTestLogger(t), db, nil)
|
||||
|
||||
app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 1})
|
||||
app.Commit()
|
||||
_, err := app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 1})
|
||||
require.NoError(t, err)
|
||||
_, err = app.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 2})
|
||||
app.Commit()
|
||||
_, err = app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 2})
|
||||
require.NoError(t, err)
|
||||
_, err = app.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
@ -609,7 +616,9 @@ func TestSetMinGasPrices(t *testing.T) {
|
||||
|
||||
func TestGetMaximumBlockGas(t *testing.T) {
|
||||
suite := NewBaseAppSuite(t)
|
||||
suite.baseApp.InitChain(&abci.RequestInitChain{})
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{})
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := suite.baseApp.NewContext(true)
|
||||
|
||||
suite.baseApp.StoreConsensusParams(ctx, cmtproto.ConsensusParams{Block: &cmtproto.BlockParams{MaxGas: 0}})
|
||||
|
||||
210
baseapp/testutil/mock/mocks.go
Normal file
210
baseapp/testutil/mock/mocks.go
Normal file
@ -0,0 +1,210 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: baseapp/abci_utils.go
|
||||
|
||||
// Package mock is a generated GoMock package.
|
||||
package mock
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
|
||||
math "cosmossdk.io/math"
|
||||
crypto "github.com/cometbft/cometbft/proto/tendermint/crypto"
|
||||
baseapp "github.com/cosmos/cosmos-sdk/baseapp"
|
||||
types "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
types0 "github.com/cosmos/cosmos-sdk/types"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockValidator is a mock of Validator interface.
|
||||
type MockValidator struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockValidatorMockRecorder
|
||||
}
|
||||
|
||||
// MockValidatorMockRecorder is the mock recorder for MockValidator.
|
||||
type MockValidatorMockRecorder struct {
|
||||
mock *MockValidator
|
||||
}
|
||||
|
||||
// NewMockValidator creates a new mock instance.
|
||||
func NewMockValidator(ctrl *gomock.Controller) *MockValidator {
|
||||
mock := &MockValidator{ctrl: ctrl}
|
||||
mock.recorder = &MockValidatorMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockValidator) EXPECT() *MockValidatorMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// BondedTokens mocks base method.
|
||||
func (m *MockValidator) BondedTokens() math.Int {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "BondedTokens")
|
||||
ret0, _ := ret[0].(math.Int)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// BondedTokens indicates an expected call of BondedTokens.
|
||||
func (mr *MockValidatorMockRecorder) BondedTokens() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BondedTokens", reflect.TypeOf((*MockValidator)(nil).BondedTokens))
|
||||
}
|
||||
|
||||
// CmtConsPublicKey mocks base method.
|
||||
func (m *MockValidator) CmtConsPublicKey() (crypto.PublicKey, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CmtConsPublicKey")
|
||||
ret0, _ := ret[0].(crypto.PublicKey)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// CmtConsPublicKey indicates an expected call of CmtConsPublicKey.
|
||||
func (mr *MockValidatorMockRecorder) CmtConsPublicKey() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CmtConsPublicKey", reflect.TypeOf((*MockValidator)(nil).CmtConsPublicKey))
|
||||
}
|
||||
|
||||
// MockValidatorStore is a mock of ValidatorStore interface.
|
||||
type MockValidatorStore struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockValidatorStoreMockRecorder
|
||||
}
|
||||
|
||||
// MockValidatorStoreMockRecorder is the mock recorder for MockValidatorStore.
|
||||
type MockValidatorStoreMockRecorder struct {
|
||||
mock *MockValidatorStore
|
||||
}
|
||||
|
||||
// NewMockValidatorStore creates a new mock instance.
|
||||
func NewMockValidatorStore(ctrl *gomock.Controller) *MockValidatorStore {
|
||||
mock := &MockValidatorStore{ctrl: ctrl}
|
||||
mock.recorder = &MockValidatorStoreMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockValidatorStore) EXPECT() *MockValidatorStoreMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GetValidatorByConsAddr mocks base method.
|
||||
func (m *MockValidatorStore) GetValidatorByConsAddr(arg0 types0.Context, arg1 types.Address) (baseapp.Validator, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetValidatorByConsAddr", arg0, arg1)
|
||||
ret0, _ := ret[0].(baseapp.Validator)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetValidatorByConsAddr indicates an expected call of GetValidatorByConsAddr.
|
||||
func (mr *MockValidatorStoreMockRecorder) GetValidatorByConsAddr(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetValidatorByConsAddr", reflect.TypeOf((*MockValidatorStore)(nil).GetValidatorByConsAddr), arg0, arg1)
|
||||
}
|
||||
|
||||
// TotalBondedTokens mocks base method.
|
||||
func (m *MockValidatorStore) TotalBondedTokens(ctx types0.Context) math.Int {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "TotalBondedTokens", ctx)
|
||||
ret0, _ := ret[0].(math.Int)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// TotalBondedTokens indicates an expected call of TotalBondedTokens.
|
||||
func (mr *MockValidatorStoreMockRecorder) TotalBondedTokens(ctx interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TotalBondedTokens", reflect.TypeOf((*MockValidatorStore)(nil).TotalBondedTokens), ctx)
|
||||
}
|
||||
|
||||
// MockGasTx is a mock of GasTx interface.
|
||||
type MockGasTx struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockGasTxMockRecorder
|
||||
}
|
||||
|
||||
// MockGasTxMockRecorder is the mock recorder for MockGasTx.
|
||||
type MockGasTxMockRecorder struct {
|
||||
mock *MockGasTx
|
||||
}
|
||||
|
||||
// NewMockGasTx creates a new mock instance.
|
||||
func NewMockGasTx(ctrl *gomock.Controller) *MockGasTx {
|
||||
mock := &MockGasTx{ctrl: ctrl}
|
||||
mock.recorder = &MockGasTxMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockGasTx) EXPECT() *MockGasTxMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GetGas mocks base method.
|
||||
func (m *MockGasTx) GetGas() uint64 {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetGas")
|
||||
ret0, _ := ret[0].(uint64)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetGas indicates an expected call of GetGas.
|
||||
func (mr *MockGasTxMockRecorder) GetGas() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetGas", reflect.TypeOf((*MockGasTx)(nil).GetGas))
|
||||
}
|
||||
|
||||
// MockProposalTxVerifier is a mock of ProposalTxVerifier interface.
|
||||
type MockProposalTxVerifier struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockProposalTxVerifierMockRecorder
|
||||
}
|
||||
|
||||
// MockProposalTxVerifierMockRecorder is the mock recorder for MockProposalTxVerifier.
|
||||
type MockProposalTxVerifierMockRecorder struct {
|
||||
mock *MockProposalTxVerifier
|
||||
}
|
||||
|
||||
// NewMockProposalTxVerifier creates a new mock instance.
|
||||
func NewMockProposalTxVerifier(ctrl *gomock.Controller) *MockProposalTxVerifier {
|
||||
mock := &MockProposalTxVerifier{ctrl: ctrl}
|
||||
mock.recorder = &MockProposalTxVerifierMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockProposalTxVerifier) EXPECT() *MockProposalTxVerifierMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// PrepareProposalVerifyTx mocks base method.
|
||||
func (m *MockProposalTxVerifier) PrepareProposalVerifyTx(tx types0.Tx) ([]byte, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "PrepareProposalVerifyTx", tx)
|
||||
ret0, _ := ret[0].([]byte)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// PrepareProposalVerifyTx indicates an expected call of PrepareProposalVerifyTx.
|
||||
func (mr *MockProposalTxVerifierMockRecorder) PrepareProposalVerifyTx(tx interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrepareProposalVerifyTx", reflect.TypeOf((*MockProposalTxVerifier)(nil).PrepareProposalVerifyTx), tx)
|
||||
}
|
||||
|
||||
// ProcessProposalVerifyTx mocks base method.
|
||||
func (m *MockProposalTxVerifier) ProcessProposalVerifyTx(txBz []byte) (types0.Tx, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ProcessProposalVerifyTx", txBz)
|
||||
ret0, _ := ret[0].(types0.Tx)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// ProcessProposalVerifyTx indicates an expected call of ProcessProposalVerifyTx.
|
||||
func (mr *MockProposalTxVerifierMockRecorder) ProcessProposalVerifyTx(txBz interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProcessProposalVerifyTx", reflect.TypeOf((*MockProposalTxVerifier)(nil).ProcessProposalVerifyTx), txBz)
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
mockgen_cmd="mockgen"
|
||||
$mockgen_cmd -source=baseapp/abci_utils.go -package mock -destination baseapp/testutil/mock/validator_store.go
|
||||
$mockgen_cmd -source=client/account_retriever.go -package mock -destination testutil/mock/account_retriever.go
|
||||
$mockgen_cmd -package mock -destination store/mock/cosmos_cosmos_db_DB.go github.com/cosmos/cosmos-db DB
|
||||
$mockgen_cmd -source=types/module/module.go -package mock -destination testutil/mock/types_module_module.go
|
||||
|
||||
Loading…
Reference in New Issue
Block a user