cosmos-sdk/baseapp/abci_utils_test.go
son trinh 585335690b
feat(tx)!: make timeout_height time based (#20870)
Co-authored-by: Marko <marko@baricevic.me>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2024-07-29 11:53:27 +00:00

797 lines
23 KiB
Go

package baseapp_test
import (
"bytes"
"sort"
"testing"
abci "github.com/cometbft/cometbft/api/cometbft/abci/v1"
cmtprotocrypto "github.com/cometbft/cometbft/api/cometbft/crypto/v1"
cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1"
cmtsecp256k1 "github.com/cometbft/cometbft/crypto/secp256k1"
cmttypes "github.com/cometbft/cometbft/types"
dbm "github.com/cosmos/cosmos-db"
protoio "github.com/cosmos/gogoproto/io"
"github.com/cosmos/gogoproto/proto"
gogotypes "github.com/cosmos/gogoproto/types"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"cosmossdk.io/core/comet"
"cosmossdk.io/core/header"
"cosmossdk.io/log"
authtx "cosmossdk.io/x/auth/tx"
"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/client"
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/mempool"
signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
)
const (
chainID = "chain-id"
)
type testValidator struct {
consAddr sdk.ConsAddress
tmPk cmtprotocrypto.PublicKey
privKey cmtsecp256k1.PrivKey
}
func newTestValidator() testValidator {
privkey := cmtsecp256k1.GenPrivKey()
pubkey := privkey.PubKey()
tmPk := cmtprotocrypto.PublicKey{
Sum: &cmtprotocrypto.PublicKey_Secp256K1{
Secp256K1: pubkey.Bytes(),
},
}
return testValidator{
consAddr: sdk.ConsAddress(pubkey.Address()),
tmPk: tmPk,
privKey: privkey,
}
}
func (t testValidator) toValidator(power int64) abci.Validator {
return abci.Validator{
Address: t.consAddr.Bytes(),
Power: power,
}
}
type ABCIUtilsTestSuite struct {
suite.Suite
valStore *mock.MockValidatorStore
vals [3]testValidator
ctx sdk.Context
}
func NewABCIUtilsTestSuite(t *testing.T) *ABCIUtilsTestSuite {
t.Helper()
// create 3 validators
s := &ABCIUtilsTestSuite{
vals: [3]testValidator{
newTestValidator(),
newTestValidator(),
newTestValidator(),
},
}
// create mock
ctrl := gomock.NewController(t)
valStore := mock.NewMockValidatorStore(ctrl)
s.valStore = valStore
// set up mock
for _, val := range s.vals {
pk, err := cryptocodec.FromCmtProtoPublicKey(val.tmPk)
require.NoError(t, err)
valStore.EXPECT().GetPubKeyByConsAddr(gomock.Any(), val.consAddr.Bytes()).Return(pk, nil).AnyTimes()
}
// create context
s.ctx = sdk.Context{}.WithConsensusParams(cmtproto.ConsensusParams{
Feature: &cmtproto.FeatureParams{
VoteExtensionsEnableHeight: &gogotypes.Int64Value{Value: 2},
},
}).WithBlockHeader(cmtproto.Header{
ChainID: chainID,
}).WithLogger(log.NewTestLogger(t))
return s
}
func TestABCIUtilsTestSuite(t *testing.T) {
suite.Run(t, NewABCIUtilsTestSuite(t))
}
// check ValidateVoteExtensions works when all nodes have CommitBlockID votes
func (s *ABCIUtilsTestSuite) TestValidateVoteExtensionsHappyPath() {
ext := []byte("vote-extension")
cve := cmtproto.CanonicalVoteExtension{
Extension: ext,
Height: 2,
Round: int64(0),
ChainId: chainID,
}
bz, err := marshalDelimitedFn(&cve)
s.Require().NoError(err)
extSig0, err := s.vals[0].privKey.Sign(bz)
s.Require().NoError(err)
extSig1, err := s.vals[1].privKey.Sign(bz)
s.Require().NoError(err)
extSig2, err := s.vals[2].privKey.Sign(bz)
s.Require().NoError(err)
s.ctx = s.ctx.WithBlockHeight(3).WithHeaderInfo(header.Info{Height: 3, ChainID: chainID}) // enable vote-extensions
llc := abci.ExtendedCommitInfo{
Round: 0,
Votes: []abci.ExtendedVoteInfo{
{
Validator: s.vals[0].toValidator(333),
VoteExtension: ext,
ExtensionSignature: extSig0,
BlockIdFlag: cmtproto.BlockIDFlagCommit,
},
{
Validator: s.vals[1].toValidator(333),
VoteExtension: ext,
ExtensionSignature: extSig1,
BlockIdFlag: cmtproto.BlockIDFlagCommit,
},
{
Validator: s.vals[2].toValidator(334),
VoteExtension: ext,
ExtensionSignature: extSig2,
BlockIdFlag: cmtproto.BlockIDFlagCommit,
},
},
}
// order + convert to last commit
llc, info := extendedCommitToLastCommit(llc)
s.ctx = s.ctx.WithCometInfo(info)
// expect-pass (votes of height 2 are included in next block)
s.Require().NoError(baseapp.ValidateVoteExtensions(s.ctx, s.valStore, llc))
}
// check ValidateVoteExtensions works when a single node has submitted a BlockID_Absent
func (s *ABCIUtilsTestSuite) TestValidateVoteExtensionsSingleVoteAbsent() {
ext := []byte("vote-extension")
cve := cmtproto.CanonicalVoteExtension{
Extension: ext,
Height: 2,
Round: int64(0),
ChainId: chainID,
}
bz, err := marshalDelimitedFn(&cve)
s.Require().NoError(err)
extSig0, err := s.vals[0].privKey.Sign(bz)
s.Require().NoError(err)
extSig2, err := s.vals[2].privKey.Sign(bz)
s.Require().NoError(err)
s.ctx = s.ctx.WithBlockHeight(3) // vote-extensions are enabled
llc := abci.ExtendedCommitInfo{
Round: 0,
Votes: []abci.ExtendedVoteInfo{
{
Validator: s.vals[0].toValidator(333),
VoteExtension: ext,
ExtensionSignature: extSig0,
BlockIdFlag: cmtproto.BlockIDFlagCommit,
},
// validator of power <1/3 is missing, so commit-info shld still be valid
{
Validator: s.vals[1].toValidator(333),
BlockIdFlag: cmtproto.BlockIDFlagAbsent,
},
{
Validator: s.vals[2].toValidator(334),
VoteExtension: ext,
ExtensionSignature: extSig2,
BlockIdFlag: cmtproto.BlockIDFlagCommit,
},
},
}
llc, info := extendedCommitToLastCommit(llc)
s.ctx = s.ctx.WithCometInfo(info)
// expect-pass (votes of height 2 are included in next block)
s.Require().NoError(baseapp.ValidateVoteExtensions(s.ctx, s.valStore, llc))
}
// check ValidateVoteExtensions works with duplicate votes
func (s *ABCIUtilsTestSuite) TestValidateVoteExtensionsDuplicateVotes() {
ext := []byte("vote-extension")
cve := cmtproto.CanonicalVoteExtension{
Extension: ext,
Height: 2,
Round: int64(0),
ChainId: chainID,
}
bz, err := marshalDelimitedFn(&cve)
s.Require().NoError(err)
extSig0, err := s.vals[0].privKey.Sign(bz)
s.Require().NoError(err)
ve := abci.ExtendedVoteInfo{
Validator: s.vals[0].toValidator(333),
VoteExtension: ext,
ExtensionSignature: extSig0,
BlockIdFlag: cmtproto.BlockIDFlagCommit,
}
ve2 := abci.ExtendedVoteInfo{
Validator: s.vals[0].toValidator(334), // use diff voting-power to dupe
VoteExtension: ext,
ExtensionSignature: extSig0,
BlockIdFlag: cmtproto.BlockIDFlagCommit,
}
llc := abci.ExtendedCommitInfo{
Round: 0,
Votes: []abci.ExtendedVoteInfo{
ve,
ve2,
},
}
s.ctx = s.ctx.WithBlockHeight(3) // vote-extensions are enabled
llc, info := extendedCommitToLastCommit(llc)
s.ctx = s.ctx.WithCometInfo(info)
// expect fail (duplicate votes)
s.Require().Error(baseapp.ValidateVoteExtensions(s.ctx, s.valStore, llc))
}
// check ValidateVoteExtensions works when a single node has submitted a BlockID_Nil
func (s *ABCIUtilsTestSuite) TestValidateVoteExtensionsSingleVoteNil() {
ext := []byte("vote-extension")
cve := cmtproto.CanonicalVoteExtension{
Extension: ext,
Height: 2,
Round: int64(0),
ChainId: chainID,
}
bz, err := marshalDelimitedFn(&cve)
s.Require().NoError(err)
extSig0, err := s.vals[0].privKey.Sign(bz)
s.Require().NoError(err)
extSig2, err := s.vals[2].privKey.Sign(bz)
s.Require().NoError(err)
llc := abci.ExtendedCommitInfo{
Round: 0,
Votes: []abci.ExtendedVoteInfo{
{
Validator: s.vals[0].toValidator(333),
VoteExtension: ext,
ExtensionSignature: extSig0,
BlockIdFlag: cmtproto.BlockIDFlagCommit,
},
// validator of power <1/3 is missing, so commit-info should still be valid
{
Validator: s.vals[1].toValidator(333),
BlockIdFlag: cmtproto.BlockIDFlagNil,
},
{
Validator: s.vals[2].toValidator(334),
VoteExtension: ext,
ExtensionSignature: extSig2,
BlockIdFlag: cmtproto.BlockIDFlagCommit,
},
},
}
s.ctx = s.ctx.WithBlockHeight(3) // vote-extensions are enabled
// create last commit
llc, info := extendedCommitToLastCommit(llc)
s.ctx = s.ctx.WithCometInfo(info)
// expect-pass (votes of height 2 are included in next block)
s.Require().NoError(baseapp.ValidateVoteExtensions(s.ctx, s.valStore, llc))
}
// check ValidateVoteExtensions works when two nodes have submitted a BlockID_Nil / BlockID_Absent
func (s *ABCIUtilsTestSuite) TestValidateVoteExtensionsTwoVotesNilAbsent() {
ext := []byte("vote-extension")
cve := cmtproto.CanonicalVoteExtension{
Extension: ext,
Height: 2,
Round: int64(0),
ChainId: chainID,
}
bz, err := marshalDelimitedFn(&cve)
s.Require().NoError(err)
extSig0, err := s.vals[0].privKey.Sign(bz)
s.Require().NoError(err)
llc := abci.ExtendedCommitInfo{
Round: 0,
Votes: []abci.ExtendedVoteInfo{
// validator of power >2/3 is missing, so commit-info should not be valid
{
Validator: s.vals[0].toValidator(333),
BlockIdFlag: cmtproto.BlockIDFlagCommit,
VoteExtension: ext,
ExtensionSignature: extSig0,
},
{
Validator: s.vals[1].toValidator(333),
BlockIdFlag: cmtproto.BlockIDFlagNil,
},
{
Validator: s.vals[2].toValidator(334),
VoteExtension: ext,
BlockIdFlag: cmtproto.BlockIDFlagAbsent,
},
},
}
s.ctx = s.ctx.WithBlockHeight(3) // vote-extensions are enabled
// create last commit
llc, info := extendedCommitToLastCommit(llc)
s.ctx = s.ctx.WithCometInfo(info)
// expect-pass (votes of height 2 are included in next block)
s.Require().Error(baseapp.ValidateVoteExtensions(s.ctx, s.valStore, llc))
}
func (s *ABCIUtilsTestSuite) TestValidateVoteExtensionsIncorrectVotingPower() {
ext := []byte("vote-extension")
cve := cmtproto.CanonicalVoteExtension{
Extension: ext,
Height: 2,
Round: int64(0),
ChainId: chainID,
}
bz, err := marshalDelimitedFn(&cve)
s.Require().NoError(err)
extSig0, err := s.vals[0].privKey.Sign(bz)
s.Require().NoError(err)
llc := abci.ExtendedCommitInfo{
Round: 0,
Votes: []abci.ExtendedVoteInfo{
// validator of power >2/3 is missing, so commit-info should not be valid
{
Validator: s.vals[0].toValidator(333),
BlockIdFlag: cmtproto.BlockIDFlagCommit,
VoteExtension: ext,
ExtensionSignature: extSig0,
},
{
Validator: s.vals[1].toValidator(333),
BlockIdFlag: cmtproto.BlockIDFlagNil,
},
{
Validator: s.vals[2].toValidator(334),
VoteExtension: ext,
BlockIdFlag: cmtproto.BlockIDFlagAbsent,
},
},
}
s.ctx = s.ctx.WithBlockHeight(3) // vote-extensions are enabled
// create last commit
llc, info := extendedCommitToLastCommit(llc)
s.ctx = s.ctx.WithCometInfo(info)
// modify voting powers to differ from the last-commit
llc.Votes[0].Validator.Power = 335
llc.Votes[2].Validator.Power = 332
// expect-pass (votes of height 2 are included in next block)
s.Require().Error(baseapp.ValidateVoteExtensions(s.ctx, s.valStore, llc))
}
func (s *ABCIUtilsTestSuite) TestValidateVoteExtensionsIncorrecOrder() {
ext := []byte("vote-extension")
cve := cmtproto.CanonicalVoteExtension{
Extension: ext,
Height: 2,
Round: int64(0),
ChainId: chainID,
}
bz, err := marshalDelimitedFn(&cve)
s.Require().NoError(err)
extSig0, err := s.vals[0].privKey.Sign(bz)
s.Require().NoError(err)
llc := abci.ExtendedCommitInfo{
Round: 0,
Votes: []abci.ExtendedVoteInfo{
// validator of power >2/3 is missing, so commit-info should not be valid
{
Validator: s.vals[0].toValidator(333),
BlockIdFlag: cmtproto.BlockIDFlagCommit,
VoteExtension: ext,
ExtensionSignature: extSig0,
},
{
Validator: s.vals[1].toValidator(333),
BlockIdFlag: cmtproto.BlockIDFlagNil,
},
{
Validator: s.vals[2].toValidator(334),
VoteExtension: ext,
BlockIdFlag: cmtproto.BlockIDFlagAbsent,
},
},
}
s.ctx = s.ctx.WithBlockHeight(3) // vote-extensions are enabled
// create last commit
llc, info := extendedCommitToLastCommit(llc)
s.ctx = s.ctx.WithCometInfo(info)
// modify voting powers to differ from the last-commit
llc.Votes[0], llc.Votes[2] = llc.Votes[2], llc.Votes[0]
// expect-pass (votes of height 2 are included in next block)
s.Require().Error(baseapp.ValidateVoteExtensions(s.ctx, s.valStore, llc))
}
func (s *ABCIUtilsTestSuite) TestDefaultProposalHandler_NoOpMempoolTxSelection() {
// create a codec for marshaling
cdc := codectestutil.CodecOptions{}.NewCodec()
baseapptestutil.RegisterInterfaces(cdc.InterfaceRegistry())
signingCtx := cdc.InterfaceRegistry().SigningContext()
// create a baseapp along with a tx config for tx generation
txConfig := authtx.NewTxConfig(cdc, signingCtx.AddressCodec(), signingCtx.ValidatorAddressCodec(), authtx.DefaultSignModes)
app := baseapp.NewBaseApp(s.T().Name(), log.NewNopLogger(), dbm.NewMemDB(), txConfig.TxDecoder())
// create a proposal handler
ph := baseapp.NewDefaultProposalHandler(mempool.NoOpMempool{}, app)
handler := ph.PrepareProposalHandler()
// build a tx
_, _, addr := testdata.KeyTestPubAddr()
builder := txConfig.NewTxBuilder()
s.Require().NoError(builder.SetMsgs(
&baseapptestutil.MsgCounter{Counter: 0, FailOnHandler: false, Signer: addr.String()},
))
builder.SetGasLimit(100)
setTxSignature(s.T(), builder, 0)
// encode the tx to be used in the proposal request
tx := builder.GetTx()
txBz, err := txConfig.TxEncoder()(tx)
s.Require().NoError(err)
s.Require().Len(txBz, 165)
txDataSize := int(cmttypes.ComputeProtoSizeForTxs([]cmttypes.Tx{txBz}))
s.Require().Equal(txDataSize, 168)
testCases := map[string]struct {
ctx sdk.Context
req *abci.PrepareProposalRequest
expectedTxs int
}{
"small max tx bytes": {
ctx: s.ctx,
req: &abci.PrepareProposalRequest{
Txs: [][]byte{txBz, txBz, txBz, txBz, txBz},
MaxTxBytes: 10,
},
expectedTxs: 0,
},
"small max gas": {
ctx: s.ctx.WithConsensusParams(cmtproto.ConsensusParams{
Block: &cmtproto.BlockParams{
MaxGas: 10,
},
}),
req: &abci.PrepareProposalRequest{
Txs: [][]byte{txBz, txBz, txBz, txBz, txBz},
MaxTxBytes: 465,
},
expectedTxs: 0,
},
"large max tx bytes": {
ctx: s.ctx,
req: &abci.PrepareProposalRequest{
Txs: [][]byte{txBz, txBz, txBz, txBz, txBz},
MaxTxBytes: 465,
},
expectedTxs: 2,
},
"large max tx bytes len calculation": {
ctx: s.ctx,
req: &abci.PrepareProposalRequest{
Txs: [][]byte{txBz, txBz, txBz, txBz, txBz},
MaxTxBytes: 504,
},
expectedTxs: 3,
},
"max gas and tx bytes": {
ctx: s.ctx.WithConsensusParams(cmtproto.ConsensusParams{
Block: &cmtproto.BlockParams{
MaxGas: 200,
},
}),
req: &abci.PrepareProposalRequest{
Txs: [][]byte{txBz, txBz, txBz, txBz, txBz},
MaxTxBytes: 465,
},
expectedTxs: 2,
},
}
for name, tc := range testCases {
s.Run(name, func() {
// iterate multiple times to ensure the tx selector is cleared each time
for i := 0; i < 6; i++ {
resp, err := handler(tc.ctx, tc.req)
s.Require().NoError(err)
s.Require().Len(resp.Txs, tc.expectedTxs)
}
})
}
}
func (s *ABCIUtilsTestSuite) TestDefaultProposalHandler_PriorityNonceMempoolTxSelection() {
cdc := codectestutil.CodecOptions{}.NewCodec()
baseapptestutil.RegisterInterfaces(cdc.InterfaceRegistry())
signingCtx := cdc.InterfaceRegistry().SigningContext()
txConfig := authtx.NewTxConfig(cdc, signingCtx.AddressCodec(), signingCtx.ValidatorAddressCodec(), authtx.DefaultSignModes)
var (
secret1 = []byte("secret1")
secret2 = []byte("secret2")
secret3 = []byte("secret3")
secret4 = []byte("secret4")
secret5 = []byte("secret5")
secret6 = []byte("secret6")
)
type testTx struct {
tx sdk.Tx
priority int64
bz []byte
size int
}
testTxs := []testTx{
// test 1
{tx: buildMsg(s.T(), txConfig, []byte(`0`), [][]byte{secret1}, []uint64{1}), priority: 10},
{tx: buildMsg(s.T(), txConfig, []byte(`12345678910`), [][]byte{secret1}, []uint64{2}), priority: 10},
{tx: buildMsg(s.T(), txConfig, []byte(`22`), [][]byte{secret1}, []uint64{3}), priority: 10},
{tx: buildMsg(s.T(), txConfig, []byte(`32`), [][]byte{secret2}, []uint64{1}), priority: 8},
// test 2
{tx: buildMsg(s.T(), txConfig, []byte(`4`), [][]byte{secret1, secret2}, []uint64{3, 3}), priority: 10},
{tx: buildMsg(s.T(), txConfig, []byte(`52345678910`), [][]byte{secret1, secret3}, []uint64{4, 3}), priority: 10},
{tx: buildMsg(s.T(), txConfig, []byte(`62`), [][]byte{secret1, secret4}, []uint64{5, 3}), priority: 8},
{tx: buildMsg(s.T(), txConfig, []byte(`72`), [][]byte{secret3, secret5}, []uint64{4, 3}), priority: 8},
{tx: buildMsg(s.T(), txConfig, []byte(`82`), [][]byte{secret2, secret6}, []uint64{4, 3}), priority: 8},
// test 3
{tx: buildMsg(s.T(), txConfig, []byte(`9`), [][]byte{secret3, secret4}, []uint64{3, 3}), priority: 10},
{tx: buildMsg(s.T(), txConfig, []byte(`1052345678910`), [][]byte{secret1, secret2}, []uint64{4, 4}), priority: 8},
{tx: buildMsg(s.T(), txConfig, []byte(`11`), [][]byte{secret1, secret2}, []uint64{5, 5}), priority: 8},
// test 4
{tx: buildMsg(s.T(), txConfig, []byte(`1252345678910`), [][]byte{secret1}, []uint64{3}), priority: 10},
{tx: buildMsg(s.T(), txConfig, []byte(`13`), [][]byte{secret1}, []uint64{5}), priority: 10},
{tx: buildMsg(s.T(), txConfig, []byte(`14`), [][]byte{secret1}, []uint64{6}), priority: 8},
}
for i := range testTxs {
bz, err := txConfig.TxEncoder()(testTxs[i].tx)
s.Require().NoError(err)
testTxs[i].bz = bz
testTxs[i].size = int(cmttypes.ComputeProtoSizeForTxs([]cmttypes.Tx{bz}))
}
s.Require().Equal(193, testTxs[0].size)
s.Require().Equal(203, testTxs[1].size)
s.Require().Equal(194, testTxs[2].size)
s.Require().Equal(194, testTxs[3].size)
s.Require().Equal(276, testTxs[4].size)
s.Require().Equal(286, testTxs[5].size)
s.Require().Equal(277, testTxs[6].size)
s.Require().Equal(277, testTxs[7].size)
s.Require().Equal(277, testTxs[8].size)
testCases := map[string]struct {
ctx sdk.Context
txInputs []testTx
req *abci.PrepareProposalRequest
handler sdk.PrepareProposalHandler
expectedTxs []int
}{
"skip same-sender non-sequential sequence and then add others txs": {
ctx: s.ctx,
txInputs: []testTx{testTxs[0], testTxs[1], testTxs[2], testTxs[3]},
req: &abci.PrepareProposalRequest{
MaxTxBytes: 193 + 194,
},
expectedTxs: []int{0, 3},
},
"skip multi-signers msg non-sequential sequence": {
ctx: s.ctx,
txInputs: []testTx{testTxs[4], testTxs[5], testTxs[6], testTxs[7], testTxs[8]},
req: &abci.PrepareProposalRequest{
MaxTxBytes: 276 + 277,
},
expectedTxs: []int{4, 8},
},
"only the first tx is added": {
// Because tx 10 is valid, tx 11 can't be valid as they have higher sequence numbers.
ctx: s.ctx,
txInputs: []testTx{testTxs[9], testTxs[10], testTxs[11]},
req: &abci.PrepareProposalRequest{
MaxTxBytes: 276 + 277,
},
expectedTxs: []int{9},
},
"no txs added": {
// Because the first tx was deemed valid but too big, the next expected valid sequence is tx[0].seq (3), so
// the rest of the txs fail because they have a seq of 4.
ctx: s.ctx,
txInputs: []testTx{testTxs[12], testTxs[13], testTxs[14]},
req: &abci.PrepareProposalRequest{
MaxTxBytes: 112,
},
expectedTxs: []int{},
},
}
for name, tc := range testCases {
s.Run(name, func() {
ctrl := gomock.NewController(s.T())
app := mock.NewMockProposalTxVerifier(ctrl)
mp := mempool.NewPriorityMempool(
mempool.PriorityNonceMempoolConfig[int64]{
TxPriority: mempool.NewDefaultTxPriority(),
MaxTx: 0,
SignerExtractor: mempool.NewDefaultSignerExtractionAdapter(),
},
)
ph := baseapp.NewDefaultProposalHandler(mp, app)
for _, v := range tc.txInputs {
app.EXPECT().PrepareProposalVerifyTx(v.tx).Return(v.bz, nil).AnyTimes()
s.NoError(mp.Insert(s.ctx.WithPriority(v.priority), v.tx))
tc.req.Txs = append(tc.req.Txs, v.bz)
}
resp, err := ph.PrepareProposalHandler()(tc.ctx, tc.req)
s.Require().NoError(err)
respTxIndexes := []int{}
for _, tx := range resp.Txs {
for i, v := range testTxs {
if bytes.Equal(tx, v.bz) {
respTxIndexes = append(respTxIndexes, i)
}
}
}
s.Require().EqualValues(tc.expectedTxs, respTxIndexes)
})
}
}
func marshalDelimitedFn(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
}
func buildMsg(t *testing.T, txConfig client.TxConfig, value []byte, secrets [][]byte, nonces []uint64) sdk.Tx {
t.Helper()
builder := txConfig.NewTxBuilder()
require.Equal(t, len(secrets), len(nonces))
signatures := make([]signingtypes.SignatureV2, 0)
for index, secret := range secrets {
nonce := nonces[index]
privKey := secp256k1.GenPrivKeyFromSecret(secret)
pubKey := privKey.PubKey()
signatures = append(signatures, signingtypes.SignatureV2{
PubKey: pubKey,
Sequence: nonce,
Data: &signingtypes.SingleSignatureData{},
})
}
_ = builder.SetMsgs(
&baseapptestutil.MsgKeyValue{
Signer: sdk.AccAddress(signatures[0].PubKey.Bytes()).String(),
Value: value,
},
)
setTxSignatureWithSecret(t, builder, signatures...)
return builder.GetTx()
}
func setTxSignatureWithSecret(t *testing.T, builder client.TxBuilder, signatures ...signingtypes.SignatureV2) {
t.Helper()
err := builder.SetSignatures(
signatures...,
)
require.NoError(t, err)
}
func extendedCommitToLastCommit(ec abci.ExtendedCommitInfo) (abci.ExtendedCommitInfo, comet.Info) {
// sort the extended commit info
sort.Sort(extendedVoteInfos(ec.Votes))
// convert the extended commit info to last commit info
lastCommit := comet.CommitInfo{
Round: ec.Round,
Votes: make([]comet.VoteInfo, len(ec.Votes)),
}
for i, vote := range ec.Votes {
lastCommit.Votes[i] = comet.VoteInfo{
Validator: comet.Validator{
Address: vote.Validator.Address,
Power: vote.Validator.Power,
},
}
}
return ec, comet.Info{
LastCommit: lastCommit,
}
}
type extendedVoteInfos []abci.ExtendedVoteInfo
func (v extendedVoteInfos) Len() int {
return len(v)
}
func (v extendedVoteInfos) Less(i, j int) bool {
if v[i].Validator.Power == v[j].Validator.Power {
return bytes.Compare(v[i].Validator.Address, v[j].Validator.Address) == -1
}
return v[i].Validator.Power > v[j].Validator.Power
}
func (v extendedVoteInfos) Swap(i, j int) {
v[i], v[j] = v[j], v[i]
}