github.com/ari-anchor/sei-tendermint@v0.0.0-20230519144642-dc826b7b56bb/internal/state/execution_test.go (about)

     1  package state_test
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/mock"
    11  	"github.com/stretchr/testify/require"
    12  	dbm "github.com/tendermint/tm-db"
    13  
    14  	abciclient "github.com/ari-anchor/sei-tendermint/abci/client"
    15  	abciclientmocks "github.com/ari-anchor/sei-tendermint/abci/client/mocks"
    16  	abci "github.com/ari-anchor/sei-tendermint/abci/types"
    17  	abcimocks "github.com/ari-anchor/sei-tendermint/abci/types/mocks"
    18  	"github.com/ari-anchor/sei-tendermint/crypto"
    19  	"github.com/ari-anchor/sei-tendermint/crypto/ed25519"
    20  	"github.com/ari-anchor/sei-tendermint/crypto/encoding"
    21  	"github.com/ari-anchor/sei-tendermint/internal/eventbus"
    22  	mpmocks "github.com/ari-anchor/sei-tendermint/internal/mempool/mocks"
    23  	"github.com/ari-anchor/sei-tendermint/internal/proxy"
    24  	"github.com/ari-anchor/sei-tendermint/internal/pubsub"
    25  	sm "github.com/ari-anchor/sei-tendermint/internal/state"
    26  	"github.com/ari-anchor/sei-tendermint/internal/state/mocks"
    27  	sf "github.com/ari-anchor/sei-tendermint/internal/state/test/factory"
    28  	"github.com/ari-anchor/sei-tendermint/internal/store"
    29  	"github.com/ari-anchor/sei-tendermint/internal/test/factory"
    30  	"github.com/ari-anchor/sei-tendermint/libs/log"
    31  	"github.com/ari-anchor/sei-tendermint/types"
    32  	"github.com/ari-anchor/sei-tendermint/version"
    33  )
    34  
    35  var (
    36  	chainID             = "execution_chain"
    37  	testPartSize uint32 = 65536
    38  )
    39  
    40  func TestApplyBlock(t *testing.T) {
    41  	app := &testApp{}
    42  	logger := log.NewNopLogger()
    43  	cc := abciclient.NewLocalClient(logger, app)
    44  	proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
    45  
    46  	ctx, cancel := context.WithCancel(context.Background())
    47  	defer cancel()
    48  
    49  	require.NoError(t, proxyApp.Start(ctx))
    50  
    51  	eventBus := eventbus.NewDefault(logger)
    52  	require.NoError(t, eventBus.Start(ctx))
    53  
    54  	state, stateDB, _ := makeState(t, 1, 1)
    55  	stateStore := sm.NewStore(stateDB)
    56  	blockStore := store.NewBlockStore(dbm.NewMemDB())
    57  	mp := &mpmocks.Mempool{}
    58  	mp.On("Lock").Return()
    59  	mp.On("Unlock").Return()
    60  	mp.On("FlushAppConn", mock.Anything).Return(nil)
    61  	mp.On("Update",
    62  		mock.Anything,
    63  		mock.Anything,
    64  		mock.Anything,
    65  		mock.Anything,
    66  		mock.Anything,
    67  		mock.Anything,
    68  		mock.Anything).Return(nil)
    69  	mp.On("TxStore").Return(nil)
    70  	blockExec := sm.NewBlockExecutor(stateStore, logger, proxyApp, mp, sm.EmptyEvidencePool{}, blockStore, eventBus, sm.NopMetrics())
    71  
    72  	block := sf.MakeBlock(state, 1, new(types.Commit))
    73  	bps, err := block.MakePartSet(testPartSize)
    74  	require.NoError(t, err)
    75  	blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
    76  
    77  	state, err = blockExec.ApplyBlock(ctx, state, blockID, block, nil)
    78  	require.NoError(t, err)
    79  
    80  	// TODO check state and mempool
    81  	assert.EqualValues(t, 1, state.Version.Consensus.App, "App version wasn't updated")
    82  }
    83  
    84  // TestFinalizeBlockDecidedLastCommit ensures we correctly send the
    85  // DecidedLastCommit to the application. The test ensures that the
    86  // DecidedLastCommit properly reflects which validators signed the preceding
    87  // block.
    88  func TestFinalizeBlockDecidedLastCommit(t *testing.T) {
    89  	ctx, cancel := context.WithCancel(context.Background())
    90  	defer cancel()
    91  
    92  	logger := log.NewNopLogger()
    93  	app := &testApp{}
    94  	cc := abciclient.NewLocalClient(logger, app)
    95  	appClient := proxy.New(cc, logger, proxy.NopMetrics())
    96  
    97  	err := appClient.Start(ctx)
    98  	require.NoError(t, err)
    99  
   100  	state, stateDB, privVals := makeState(t, 7, 1)
   101  	stateStore := sm.NewStore(stateDB)
   102  	absentSig := types.NewExtendedCommitSigAbsent()
   103  
   104  	testCases := []struct {
   105  		name             string
   106  		absentCommitSigs map[int]bool
   107  	}{
   108  		{"none absent", map[int]bool{}},
   109  		{"one absent", map[int]bool{1: true}},
   110  		{"multiple absent", map[int]bool{1: true, 3: true}},
   111  	}
   112  
   113  	for _, tc := range testCases {
   114  		t.Run(tc.name, func(t *testing.T) {
   115  			blockStore := store.NewBlockStore(dbm.NewMemDB())
   116  			evpool := &mocks.EvidencePool{}
   117  			evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, 0)
   118  			evpool.On("Update", ctx, mock.Anything, mock.Anything).Return()
   119  			evpool.On("CheckEvidence", ctx, mock.Anything).Return(nil)
   120  			mp := &mpmocks.Mempool{}
   121  			mp.On("Lock").Return()
   122  			mp.On("Unlock").Return()
   123  			mp.On("FlushAppConn", mock.Anything).Return(nil)
   124  			mp.On("Update",
   125  				mock.Anything,
   126  				mock.Anything,
   127  				mock.Anything,
   128  				mock.Anything,
   129  				mock.Anything,
   130  				mock.Anything,
   131  				mock.Anything).Return(nil)
   132  			mp.On("TxStore").Return(nil)
   133  
   134  			eventBus := eventbus.NewDefault(logger)
   135  			require.NoError(t, eventBus.Start(ctx))
   136  
   137  			blockExec := sm.NewBlockExecutor(stateStore, log.NewNopLogger(), appClient, mp, evpool, blockStore, eventBus, sm.NopMetrics())
   138  			state, _, lastCommit := makeAndCommitGoodBlock(ctx, t, state, 1, new(types.Commit), state.NextValidators.Validators[0].Address, blockExec, privVals, nil)
   139  
   140  			for idx, isAbsent := range tc.absentCommitSigs {
   141  				if isAbsent {
   142  					lastCommit.ExtendedSignatures[idx] = absentSig
   143  				}
   144  			}
   145  
   146  			// block for height 2
   147  			block := sf.MakeBlock(state, 2, lastCommit.ToCommit())
   148  			bps, err := block.MakePartSet(testPartSize)
   149  			require.NoError(t, err)
   150  			blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
   151  			_, err = blockExec.ApplyBlock(ctx, state, blockID, block, nil)
   152  			require.NoError(t, err)
   153  
   154  			// -> app receives a list of validators with a bool indicating if they signed
   155  			for i, v := range app.CommitVotes {
   156  				_, absent := tc.absentCommitSigs[i]
   157  				assert.Equal(t, !absent, v.SignedLastBlock)
   158  			}
   159  		})
   160  	}
   161  }
   162  
   163  // TestFinalizeBlockByzantineValidators ensures we send byzantine validators list.
   164  func TestFinalizeBlockByzantineValidators(t *testing.T) {
   165  	ctx, cancel := context.WithCancel(context.Background())
   166  	defer cancel()
   167  
   168  	app := &testApp{}
   169  	logger := log.NewNopLogger()
   170  	cc := abciclient.NewLocalClient(logger, app)
   171  	proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
   172  	err := proxyApp.Start(ctx)
   173  	require.NoError(t, err)
   174  
   175  	state, stateDB, privVals := makeState(t, 1, 1)
   176  	stateStore := sm.NewStore(stateDB)
   177  
   178  	defaultEvidenceTime := time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
   179  	privVal := privVals[state.Validators.Validators[0].Address.String()]
   180  	blockID := makeBlockID([]byte("headerhash"), 1000, []byte("partshash"))
   181  	header := &types.Header{
   182  		Version:            version.Consensus{Block: version.BlockProtocol, App: 1},
   183  		ChainID:            state.ChainID,
   184  		Height:             10,
   185  		Time:               defaultEvidenceTime,
   186  		LastBlockID:        blockID,
   187  		LastCommitHash:     crypto.CRandBytes(crypto.HashSize),
   188  		DataHash:           crypto.CRandBytes(crypto.HashSize),
   189  		ValidatorsHash:     state.Validators.Hash(),
   190  		NextValidatorsHash: state.Validators.Hash(),
   191  		ConsensusHash:      crypto.CRandBytes(crypto.HashSize),
   192  		AppHash:            crypto.CRandBytes(crypto.HashSize),
   193  		LastResultsHash:    crypto.CRandBytes(crypto.HashSize),
   194  		EvidenceHash:       crypto.CRandBytes(crypto.HashSize),
   195  		ProposerAddress:    crypto.CRandBytes(crypto.AddressSize),
   196  	}
   197  
   198  	// we don't need to worry about validating the evidence as long as they pass validate basic
   199  	dve, err := types.NewMockDuplicateVoteEvidenceWithValidator(ctx, 3, defaultEvidenceTime, privVal, state.ChainID)
   200  	require.NoError(t, err)
   201  	dve.ValidatorPower = 1000
   202  	lcae := &types.LightClientAttackEvidence{
   203  		ConflictingBlock: &types.LightBlock{
   204  			SignedHeader: &types.SignedHeader{
   205  				Header: header,
   206  				Commit: &types.Commit{
   207  					Height:  10,
   208  					BlockID: makeBlockID(header.Hash(), 100, []byte("partshash")),
   209  					Signatures: []types.CommitSig{{
   210  						BlockIDFlag:      types.BlockIDFlagNil,
   211  						ValidatorAddress: crypto.AddressHash([]byte("validator_address")),
   212  						Timestamp:        defaultEvidenceTime,
   213  						Signature:        crypto.CRandBytes(types.MaxSignatureSize)}},
   214  				},
   215  			},
   216  			ValidatorSet: state.Validators,
   217  		},
   218  		CommonHeight:        8,
   219  		ByzantineValidators: []*types.Validator{state.Validators.Validators[0]},
   220  		TotalVotingPower:    12,
   221  		Timestamp:           defaultEvidenceTime,
   222  	}
   223  
   224  	ev := []types.Evidence{dve, lcae}
   225  
   226  	abciMb := []abci.Misbehavior{
   227  		{
   228  			Type:             abci.MisbehaviorType_DUPLICATE_VOTE,
   229  			Height:           3,
   230  			Time:             defaultEvidenceTime,
   231  			Validator:        types.TM2PB.Validator(state.Validators.Validators[0]),
   232  			TotalVotingPower: 10,
   233  		},
   234  		{
   235  			Type:             abci.MisbehaviorType_LIGHT_CLIENT_ATTACK,
   236  			Height:           8,
   237  			Time:             defaultEvidenceTime,
   238  			Validator:        types.TM2PB.Validator(state.Validators.Validators[0]),
   239  			TotalVotingPower: 12,
   240  		},
   241  	}
   242  
   243  	evpool := &mocks.EvidencePool{}
   244  	evpool.On("PendingEvidence", mock.AnythingOfType("int64")).Return(ev, int64(100))
   245  	evpool.On("Update", ctx, mock.AnythingOfType("state.State"), mock.AnythingOfType("types.EvidenceList")).Return()
   246  	evpool.On("CheckEvidence", ctx, mock.AnythingOfType("types.EvidenceList")).Return(nil)
   247  	mp := &mpmocks.Mempool{}
   248  	mp.On("Lock").Return()
   249  	mp.On("Unlock").Return()
   250  	mp.On("FlushAppConn", mock.Anything).Return(nil)
   251  	mp.On("Update",
   252  		mock.Anything,
   253  		mock.Anything,
   254  		mock.Anything,
   255  		mock.Anything,
   256  		mock.Anything,
   257  		mock.Anything,
   258  		mock.Anything).Return(nil)
   259  	mp.On("TxStore").Return(nil)
   260  
   261  	eventBus := eventbus.NewDefault(logger)
   262  	require.NoError(t, eventBus.Start(ctx))
   263  
   264  	blockStore := store.NewBlockStore(dbm.NewMemDB())
   265  
   266  	blockExec := sm.NewBlockExecutor(stateStore, log.NewNopLogger(), proxyApp, mp, evpool, blockStore, eventBus, sm.NopMetrics())
   267  
   268  	block := sf.MakeBlock(state, 1, new(types.Commit))
   269  	block.Evidence = ev
   270  	block.Header.EvidenceHash = block.Evidence.Hash()
   271  	bps, err := block.MakePartSet(testPartSize)
   272  	require.NoError(t, err)
   273  
   274  	blockID = types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
   275  
   276  	_, err = blockExec.ApplyBlock(ctx, state, blockID, block, nil)
   277  	require.NoError(t, err)
   278  
   279  	// TODO check state and mempool
   280  	assert.Equal(t, abciMb, app.ByzantineValidators)
   281  }
   282  
   283  func TestProcessProposal(t *testing.T) {
   284  	const height = 2
   285  	txs := factory.MakeNTxs(height, 10)
   286  	ctx, cancel := context.WithCancel(context.Background())
   287  	defer cancel()
   288  
   289  	app := abcimocks.NewApplication(t)
   290  	logger := log.NewNopLogger()
   291  	cc := abciclient.NewLocalClient(logger, app)
   292  	proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
   293  	err := proxyApp.Start(ctx)
   294  	require.NoError(t, err)
   295  
   296  	state, stateDB, privVals := makeState(t, 1, height)
   297  	stateStore := sm.NewStore(stateDB)
   298  	blockStore := store.NewBlockStore(dbm.NewMemDB())
   299  
   300  	eventBus := eventbus.NewDefault(logger)
   301  	require.NoError(t, eventBus.Start(ctx))
   302  
   303  	mp := &mpmocks.Mempool{}
   304  	mp.On("TxStore").Return(nil)
   305  	blockExec := sm.NewBlockExecutor(
   306  		stateStore,
   307  		logger,
   308  		proxyApp,
   309  		mp,
   310  		sm.EmptyEvidencePool{},
   311  		blockStore,
   312  		eventBus,
   313  		sm.NopMetrics(),
   314  	)
   315  
   316  	block0 := sf.MakeBlock(state, height-1, new(types.Commit))
   317  	lastCommitSig := []types.CommitSig{}
   318  	partSet, err := block0.MakePartSet(types.BlockPartSizeBytes)
   319  	require.NoError(t, err)
   320  	blockID := types.BlockID{Hash: block0.Hash(), PartSetHeader: partSet.Header()}
   321  	voteInfos := []abci.VoteInfo{}
   322  	for _, privVal := range privVals {
   323  		vote, err := factory.MakeVote(ctx, privVal, block0.Header.ChainID, 0, 0, 0, 2, blockID, time.Now())
   324  		require.NoError(t, err)
   325  		pk, err := privVal.GetPubKey(ctx)
   326  		require.NoError(t, err)
   327  		addr := pk.Address()
   328  		voteInfos = append(voteInfos,
   329  			abci.VoteInfo{
   330  				SignedLastBlock: true,
   331  				Validator: abci.Validator{
   332  					Address: addr,
   333  					Power:   1000,
   334  				},
   335  			})
   336  		lastCommitSig = append(lastCommitSig, vote.CommitSig())
   337  	}
   338  
   339  	block1 := sf.MakeBlock(state, height, &types.Commit{
   340  		Height:     height - 1,
   341  		Signatures: lastCommitSig,
   342  	})
   343  	block1.Txs = txs
   344  
   345  	expectedRpp := &abci.RequestProcessProposal{
   346  		Txs:                 block1.Txs.ToSliceOfBytes(),
   347  		Hash:                block1.Hash(),
   348  		Height:              block1.Header.Height,
   349  		Time:                block1.Header.Time,
   350  		ByzantineValidators: block1.Evidence.ToABCI(),
   351  		ProposedLastCommit: abci.CommitInfo{
   352  			Round: 0,
   353  			Votes: voteInfos,
   354  		},
   355  		NextValidatorsHash:    block1.NextValidatorsHash,
   356  		ProposerAddress:       block1.ProposerAddress,
   357  		AppHash:               block1.AppHash,
   358  		ValidatorsHash:        block1.ValidatorsHash,
   359  		ConsensusHash:         block1.ConsensusHash,
   360  		DataHash:              block1.DataHash,
   361  		EvidenceHash:          block1.EvidenceHash,
   362  		LastBlockHash:         block1.LastBlockID.Hash,
   363  		LastBlockPartSetTotal: int64(block1.LastBlockID.PartSetHeader.Total),
   364  		LastBlockPartSetHash:  block1.LastBlockID.Hash,
   365  		LastCommitHash:        block1.LastCommitHash,
   366  		LastResultsHash:       block1.LastResultsHash,
   367  	}
   368  
   369  	app.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil)
   370  	acceptBlock, err := blockExec.ProcessProposal(ctx, block1, state)
   371  	require.NoError(t, err)
   372  	require.True(t, acceptBlock)
   373  	app.AssertExpectations(t)
   374  	app.AssertCalled(t, "ProcessProposal", ctx, expectedRpp)
   375  }
   376  
   377  func TestValidateValidatorUpdates(t *testing.T) {
   378  	pubkey1 := ed25519.GenPrivKey().PubKey()
   379  	pubkey2 := ed25519.GenPrivKey().PubKey()
   380  	pk1, err := encoding.PubKeyToProto(pubkey1)
   381  	assert.NoError(t, err)
   382  	pk2, err := encoding.PubKeyToProto(pubkey2)
   383  	assert.NoError(t, err)
   384  
   385  	defaultValidatorParams := types.ValidatorParams{PubKeyTypes: []string{types.ABCIPubKeyTypeEd25519}}
   386  
   387  	testCases := []struct {
   388  		name string
   389  
   390  		abciUpdates     []abci.ValidatorUpdate
   391  		validatorParams types.ValidatorParams
   392  
   393  		shouldErr bool
   394  	}{
   395  		{
   396  			"adding a validator is OK",
   397  			[]abci.ValidatorUpdate{{PubKey: pk2, Power: 20}},
   398  			defaultValidatorParams,
   399  			false,
   400  		},
   401  		{
   402  			"updating a validator is OK",
   403  			[]abci.ValidatorUpdate{{PubKey: pk1, Power: 20}},
   404  			defaultValidatorParams,
   405  			false,
   406  		},
   407  		{
   408  			"removing a validator is OK",
   409  			[]abci.ValidatorUpdate{{PubKey: pk2, Power: 0}},
   410  			defaultValidatorParams,
   411  			false,
   412  		},
   413  		{
   414  			"adding a validator with negative power results in error",
   415  			[]abci.ValidatorUpdate{{PubKey: pk2, Power: -100}},
   416  			defaultValidatorParams,
   417  			true,
   418  		},
   419  	}
   420  
   421  	for _, tc := range testCases {
   422  		tc := tc
   423  		t.Run(tc.name, func(t *testing.T) {
   424  			err := sm.ValidateValidatorUpdates(tc.abciUpdates, tc.validatorParams)
   425  			if tc.shouldErr {
   426  				assert.Error(t, err)
   427  			} else {
   428  				assert.NoError(t, err)
   429  			}
   430  		})
   431  	}
   432  }
   433  
   434  func TestUpdateValidators(t *testing.T) {
   435  	pubkey1 := ed25519.GenPrivKey().PubKey()
   436  	val1 := types.NewValidator(pubkey1, 10)
   437  	pubkey2 := ed25519.GenPrivKey().PubKey()
   438  	val2 := types.NewValidator(pubkey2, 20)
   439  
   440  	pk, err := encoding.PubKeyToProto(pubkey1)
   441  	require.NoError(t, err)
   442  	pk2, err := encoding.PubKeyToProto(pubkey2)
   443  	require.NoError(t, err)
   444  
   445  	testCases := []struct {
   446  		name string
   447  
   448  		currentSet  *types.ValidatorSet
   449  		abciUpdates []abci.ValidatorUpdate
   450  
   451  		resultingSet *types.ValidatorSet
   452  		shouldErr    bool
   453  	}{
   454  		{
   455  			"adding a validator is OK",
   456  			types.NewValidatorSet([]*types.Validator{val1}),
   457  			[]abci.ValidatorUpdate{{PubKey: pk2, Power: 20}},
   458  			types.NewValidatorSet([]*types.Validator{val1, val2}),
   459  			false,
   460  		},
   461  		{
   462  			"updating a validator is OK",
   463  			types.NewValidatorSet([]*types.Validator{val1}),
   464  			[]abci.ValidatorUpdate{{PubKey: pk, Power: 20}},
   465  			types.NewValidatorSet([]*types.Validator{types.NewValidator(pubkey1, 20)}),
   466  			false,
   467  		},
   468  		{
   469  			"removing a validator is OK",
   470  			types.NewValidatorSet([]*types.Validator{val1, val2}),
   471  			[]abci.ValidatorUpdate{{PubKey: pk2, Power: 0}},
   472  			types.NewValidatorSet([]*types.Validator{val1}),
   473  			false,
   474  		},
   475  		{
   476  			"removing a non-existing validator results in error",
   477  			types.NewValidatorSet([]*types.Validator{val1}),
   478  			[]abci.ValidatorUpdate{{PubKey: pk2, Power: 0}},
   479  			types.NewValidatorSet([]*types.Validator{val1}),
   480  			true,
   481  		},
   482  	}
   483  
   484  	for _, tc := range testCases {
   485  		tc := tc
   486  		t.Run(tc.name, func(t *testing.T) {
   487  			updates, err := types.PB2TM.ValidatorUpdates(tc.abciUpdates)
   488  			assert.NoError(t, err)
   489  			err = tc.currentSet.UpdateWithChangeSet(updates)
   490  			if tc.shouldErr {
   491  				assert.Error(t, err)
   492  			} else {
   493  				assert.NoError(t, err)
   494  				require.Equal(t, tc.resultingSet.Size(), tc.currentSet.Size())
   495  
   496  				assert.Equal(t, tc.resultingSet.TotalVotingPower(), tc.currentSet.TotalVotingPower())
   497  
   498  				assert.Equal(t, tc.resultingSet.Validators[0].Address, tc.currentSet.Validators[0].Address)
   499  				if tc.resultingSet.Size() > 1 {
   500  					assert.Equal(t, tc.resultingSet.Validators[1].Address, tc.currentSet.Validators[1].Address)
   501  				}
   502  			}
   503  		})
   504  	}
   505  }
   506  
   507  // TestFinalizeBlockValidatorUpdates ensures we update validator set and send an event.
   508  func TestFinalizeBlockValidatorUpdates(t *testing.T) {
   509  	ctx, cancel := context.WithCancel(context.Background())
   510  	defer cancel()
   511  
   512  	app := &testApp{}
   513  	logger := log.NewNopLogger()
   514  	cc := abciclient.NewLocalClient(logger, app)
   515  	proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
   516  	err := proxyApp.Start(ctx)
   517  	require.NoError(t, err)
   518  
   519  	state, stateDB, _ := makeState(t, 1, 1)
   520  	stateStore := sm.NewStore(stateDB)
   521  	blockStore := store.NewBlockStore(dbm.NewMemDB())
   522  	mp := &mpmocks.Mempool{}
   523  	mp.On("Lock").Return()
   524  	mp.On("Unlock").Return()
   525  	mp.On("FlushAppConn", mock.Anything).Return(nil)
   526  	mp.On("Update",
   527  		mock.Anything,
   528  		mock.Anything,
   529  		mock.Anything,
   530  		mock.Anything,
   531  		mock.Anything,
   532  		mock.Anything,
   533  		mock.Anything).Return(nil)
   534  	mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs{})
   535  	mp.On("TxStore").Return(nil)
   536  
   537  	eventBus := eventbus.NewDefault(logger)
   538  	require.NoError(t, eventBus.Start(ctx))
   539  
   540  	blockExec := sm.NewBlockExecutor(
   541  		stateStore,
   542  		logger,
   543  		proxyApp,
   544  		mp,
   545  		sm.EmptyEvidencePool{},
   546  		blockStore,
   547  		eventBus,
   548  		sm.NopMetrics(),
   549  	)
   550  
   551  	updatesSub, err := eventBus.SubscribeWithArgs(ctx, pubsub.SubscribeArgs{
   552  		ClientID: "TestFinalizeBlockValidatorUpdates",
   553  		Query:    types.EventQueryValidatorSetUpdates,
   554  	})
   555  	require.NoError(t, err)
   556  
   557  	block := sf.MakeBlock(state, 1, new(types.Commit))
   558  	bps, err := block.MakePartSet(testPartSize)
   559  	require.NoError(t, err)
   560  	blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
   561  
   562  	pubkey := ed25519.GenPrivKey().PubKey()
   563  	pk, err := encoding.PubKeyToProto(pubkey)
   564  	require.NoError(t, err)
   565  	app.ValidatorUpdates = []abci.ValidatorUpdate{
   566  		{PubKey: pk, Power: 10},
   567  	}
   568  
   569  	state, err = blockExec.ApplyBlock(ctx, state, blockID, block, nil)
   570  	require.NoError(t, err)
   571  	// test new validator was added to NextValidators
   572  	if assert.Equal(t, state.Validators.Size()+1, state.NextValidators.Size()) {
   573  		idx, _ := state.NextValidators.GetByAddress(pubkey.Address())
   574  		if idx < 0 {
   575  			t.Fatalf("can't find address %v in the set %v", pubkey.Address(), state.NextValidators)
   576  		}
   577  	}
   578  
   579  	// test we threw an event
   580  	ctx, cancel = context.WithTimeout(ctx, 1*time.Second)
   581  	defer cancel()
   582  	msg, err := updatesSub.Next(ctx)
   583  	require.NoError(t, err)
   584  	event, ok := msg.Data().(types.EventDataValidatorSetUpdates)
   585  	require.True(t, ok, "Expected event of type EventDataValidatorSetUpdates, got %T", msg.Data())
   586  	if assert.NotEmpty(t, event.ValidatorUpdates) {
   587  		assert.Equal(t, pubkey, event.ValidatorUpdates[0].PubKey)
   588  		assert.EqualValues(t, 10, event.ValidatorUpdates[0].VotingPower)
   589  	}
   590  }
   591  
   592  // TestFinalizeBlockValidatorUpdatesResultingInEmptySet checks that processing validator updates that
   593  // would result in empty set causes no panic, an error is raised and NextValidators is not updated
   594  func TestFinalizeBlockValidatorUpdatesResultingInEmptySet(t *testing.T) {
   595  	ctx, cancel := context.WithCancel(context.Background())
   596  	defer cancel()
   597  
   598  	app := &testApp{}
   599  	logger := log.NewNopLogger()
   600  	cc := abciclient.NewLocalClient(logger, app)
   601  	proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
   602  	err := proxyApp.Start(ctx)
   603  	require.NoError(t, err)
   604  
   605  	eventBus := eventbus.NewDefault(logger)
   606  	require.NoError(t, eventBus.Start(ctx))
   607  
   608  	state, stateDB, _ := makeState(t, 1, 1)
   609  	stateStore := sm.NewStore(stateDB)
   610  	blockStore := store.NewBlockStore(dbm.NewMemDB())
   611  	mp := &mpmocks.Mempool{}
   612  	mp.On("TxStore").Return(nil)
   613  	blockExec := sm.NewBlockExecutor(
   614  		stateStore,
   615  		log.NewNopLogger(),
   616  		proxyApp,
   617  		mp,
   618  		sm.EmptyEvidencePool{},
   619  		blockStore,
   620  		eventBus,
   621  		sm.NopMetrics(),
   622  	)
   623  
   624  	block := sf.MakeBlock(state, 1, new(types.Commit))
   625  	bps, err := block.MakePartSet(testPartSize)
   626  	require.NoError(t, err)
   627  	blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
   628  
   629  	vp, err := encoding.PubKeyToProto(state.Validators.Validators[0].PubKey)
   630  	require.NoError(t, err)
   631  	// Remove the only validator
   632  	app.ValidatorUpdates = []abci.ValidatorUpdate{
   633  		{PubKey: vp, Power: 0},
   634  	}
   635  
   636  	assert.NotPanics(t, func() { state, err = blockExec.ApplyBlock(ctx, state, blockID, block, nil) })
   637  	assert.Error(t, err)
   638  	assert.NotEmpty(t, state.NextValidators.Validators)
   639  }
   640  
   641  func TestEmptyPrepareProposal(t *testing.T) {
   642  	const height = 2
   643  	ctx, cancel := context.WithCancel(context.Background())
   644  	defer cancel()
   645  
   646  	logger := log.NewNopLogger()
   647  
   648  	eventBus := eventbus.NewDefault(logger)
   649  	require.NoError(t, eventBus.Start(ctx))
   650  
   651  	app := abcimocks.NewApplication(t)
   652  	app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{}, nil)
   653  	cc := abciclient.NewLocalClient(logger, app)
   654  	proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
   655  	err := proxyApp.Start(ctx)
   656  	require.NoError(t, err)
   657  
   658  	state, stateDB, privVals := makeState(t, 1, height)
   659  	stateStore := sm.NewStore(stateDB)
   660  	mp := &mpmocks.Mempool{}
   661  	mp.On("Lock").Return()
   662  	mp.On("Unlock").Return()
   663  	mp.On("FlushAppConn", mock.Anything).Return(nil)
   664  	mp.On("Update",
   665  		mock.Anything,
   666  		mock.Anything,
   667  		mock.Anything,
   668  		mock.Anything,
   669  		mock.Anything,
   670  		mock.Anything,
   671  		mock.Anything).Return(nil)
   672  	mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs{})
   673  	mp.On("TxStore").Return(nil)
   674  
   675  	blockExec := sm.NewBlockExecutor(
   676  		stateStore,
   677  		logger,
   678  		proxyApp,
   679  		mp,
   680  		sm.EmptyEvidencePool{},
   681  		nil,
   682  		eventBus,
   683  		sm.NopMetrics(),
   684  	)
   685  	pa, _ := state.Validators.GetByIndex(0)
   686  	commit, _ := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
   687  	_, err = blockExec.CreateProposalBlock(ctx, height, state, commit, pa)
   688  	require.NoError(t, err)
   689  }
   690  
   691  // TestPrepareProposalErrorOnNonExistingRemoved tests that the block creation logic returns
   692  // an error if the ResponsePrepareProposal returned from the application marks
   693  //
   694  //	a transaction as REMOVED that was not present in the original proposal.
   695  func TestPrepareProposalErrorOnNonExistingRemoved(t *testing.T) {
   696  	const height = 2
   697  	ctx, cancel := context.WithCancel(context.Background())
   698  	defer cancel()
   699  
   700  	logger := log.NewNopLogger()
   701  	eventBus := eventbus.NewDefault(logger)
   702  	require.NoError(t, eventBus.Start(ctx))
   703  
   704  	state, stateDB, privVals := makeState(t, 1, height)
   705  	stateStore := sm.NewStore(stateDB)
   706  
   707  	evpool := &mocks.EvidencePool{}
   708  	evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0))
   709  
   710  	mp := &mpmocks.Mempool{}
   711  	mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs{})
   712  
   713  	app := abcimocks.NewApplication(t)
   714  
   715  	// create an invalid ResponsePrepareProposal
   716  	rpp := &abci.ResponsePrepareProposal{
   717  		TxRecords: []*abci.TxRecord{
   718  			{
   719  				Action: abci.TxRecord_REMOVED,
   720  				Tx:     []byte("new tx"),
   721  			},
   722  		},
   723  	}
   724  	app.On("PrepareProposal", mock.Anything, mock.Anything).Return(rpp, nil)
   725  
   726  	cc := abciclient.NewLocalClient(logger, app)
   727  	proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
   728  	err := proxyApp.Start(ctx)
   729  	require.NoError(t, err)
   730  
   731  	blockExec := sm.NewBlockExecutor(
   732  		stateStore,
   733  		logger,
   734  		proxyApp,
   735  		mp,
   736  		evpool,
   737  		nil,
   738  		eventBus,
   739  		sm.NopMetrics(),
   740  	)
   741  	pa, _ := state.Validators.GetByIndex(0)
   742  	commit, _ := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
   743  	block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa)
   744  	require.ErrorContains(t, err, "new transaction incorrectly marked as removed")
   745  	require.Nil(t, block)
   746  
   747  	mp.AssertExpectations(t)
   748  }
   749  
   750  // TestPrepareProposalRemoveTxs tests that any transactions marked as REMOVED
   751  // are not included in the block produced by CreateProposalBlock. The test also
   752  // ensures that any transactions removed are also removed from the mempool.
   753  func TestPrepareProposalRemoveTxs(t *testing.T) {
   754  	const height = 2
   755  	ctx, cancel := context.WithCancel(context.Background())
   756  	defer cancel()
   757  
   758  	logger := log.NewNopLogger()
   759  	eventBus := eventbus.NewDefault(logger)
   760  	require.NoError(t, eventBus.Start(ctx))
   761  
   762  	state, stateDB, privVals := makeState(t, 1, height)
   763  	stateStore := sm.NewStore(stateDB)
   764  
   765  	evpool := &mocks.EvidencePool{}
   766  	evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0))
   767  
   768  	txs := factory.MakeNTxs(height, 10)
   769  	mp := &mpmocks.Mempool{}
   770  	mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs))
   771  
   772  	trs := txsToTxRecords(types.Txs(txs))
   773  	trs[0].Action = abci.TxRecord_REMOVED
   774  	trs[1].Action = abci.TxRecord_REMOVED
   775  	mp.On("RemoveTxByKey", mock.Anything).Return(nil).Twice()
   776  
   777  	app := abcimocks.NewApplication(t)
   778  	app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{
   779  		TxRecords: trs,
   780  	}, nil)
   781  
   782  	cc := abciclient.NewLocalClient(logger, app)
   783  	proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
   784  	err := proxyApp.Start(ctx)
   785  	require.NoError(t, err)
   786  
   787  	blockExec := sm.NewBlockExecutor(
   788  		stateStore,
   789  		logger,
   790  		proxyApp,
   791  		mp,
   792  		evpool,
   793  		nil,
   794  		eventBus,
   795  		sm.NopMetrics(),
   796  	)
   797  	pa, _ := state.Validators.GetByIndex(0)
   798  	commit, _ := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
   799  	block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa)
   800  	require.NoError(t, err)
   801  	require.Len(t, block.Data.Txs.ToSliceOfBytes(), len(trs)-2)
   802  
   803  	require.Equal(t, -1, block.Data.Txs.Index(types.Tx(trs[0].Tx)))
   804  	require.Equal(t, -1, block.Data.Txs.Index(types.Tx(trs[1].Tx)))
   805  
   806  	mp.AssertCalled(t, "RemoveTxByKey", types.Tx(trs[0].Tx).Key())
   807  	mp.AssertCalled(t, "RemoveTxByKey", types.Tx(trs[1].Tx).Key())
   808  	mp.AssertExpectations(t)
   809  }
   810  
   811  // TestPrepareProposalAddedTxsIncluded tests that any transactions marked as ADDED
   812  // in the prepare proposal response are included in the block.
   813  func TestPrepareProposalAddedTxsIncluded(t *testing.T) {
   814  	const height = 2
   815  	ctx, cancel := context.WithCancel(context.Background())
   816  	defer cancel()
   817  
   818  	logger := log.NewNopLogger()
   819  	eventBus := eventbus.NewDefault(logger)
   820  	require.NoError(t, eventBus.Start(ctx))
   821  
   822  	state, stateDB, privVals := makeState(t, 1, height)
   823  	stateStore := sm.NewStore(stateDB)
   824  
   825  	evpool := &mocks.EvidencePool{}
   826  	evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0))
   827  
   828  	txs := factory.MakeNTxs(height, 10)
   829  	mp := &mpmocks.Mempool{}
   830  	mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs[2:]))
   831  
   832  	trs := txsToTxRecords(types.Txs(txs))
   833  	trs[0].Action = abci.TxRecord_ADDED
   834  	trs[1].Action = abci.TxRecord_ADDED
   835  
   836  	app := abcimocks.NewApplication(t)
   837  	app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{
   838  		TxRecords: trs,
   839  	}, nil)
   840  
   841  	cc := abciclient.NewLocalClient(logger, app)
   842  	proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
   843  	err := proxyApp.Start(ctx)
   844  	require.NoError(t, err)
   845  
   846  	blockExec := sm.NewBlockExecutor(
   847  		stateStore,
   848  		logger,
   849  		proxyApp,
   850  		mp,
   851  		evpool,
   852  		nil,
   853  		eventBus,
   854  		sm.NopMetrics(),
   855  	)
   856  	pa, _ := state.Validators.GetByIndex(0)
   857  	commit, _ := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
   858  	block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa)
   859  	require.NoError(t, err)
   860  
   861  	require.Equal(t, txs[0], block.Data.Txs[0])
   862  	require.Equal(t, txs[1], block.Data.Txs[1])
   863  
   864  	mp.AssertExpectations(t)
   865  }
   866  
   867  // TestPrepareProposalReorderTxs tests that CreateBlock produces a block with transactions
   868  // in the order matching the order they are returned from PrepareProposal.
   869  func TestPrepareProposalReorderTxs(t *testing.T) {
   870  	const height = 2
   871  	ctx, cancel := context.WithCancel(context.Background())
   872  	defer cancel()
   873  
   874  	logger := log.NewNopLogger()
   875  	eventBus := eventbus.NewDefault(logger)
   876  	require.NoError(t, eventBus.Start(ctx))
   877  
   878  	state, stateDB, privVals := makeState(t, 1, height)
   879  	stateStore := sm.NewStore(stateDB)
   880  
   881  	evpool := &mocks.EvidencePool{}
   882  	evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0))
   883  
   884  	txs := factory.MakeNTxs(height, 10)
   885  	mp := &mpmocks.Mempool{}
   886  	mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs))
   887  
   888  	trs := txsToTxRecords(types.Txs(txs))
   889  	trs = trs[2:]
   890  	trs = append(trs[len(trs)/2:], trs[:len(trs)/2]...)
   891  
   892  	app := abcimocks.NewApplication(t)
   893  	app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{
   894  		TxRecords: trs,
   895  	}, nil)
   896  
   897  	cc := abciclient.NewLocalClient(logger, app)
   898  	proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
   899  	err := proxyApp.Start(ctx)
   900  	require.NoError(t, err)
   901  
   902  	blockExec := sm.NewBlockExecutor(
   903  		stateStore,
   904  		logger,
   905  		proxyApp,
   906  		mp,
   907  		evpool,
   908  		nil,
   909  		eventBus,
   910  		sm.NopMetrics(),
   911  	)
   912  	pa, _ := state.Validators.GetByIndex(0)
   913  	commit, _ := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
   914  	block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa)
   915  	require.NoError(t, err)
   916  	for i, tx := range block.Data.Txs {
   917  		require.Equal(t, types.Tx(trs[i].Tx), tx)
   918  	}
   919  
   920  	mp.AssertExpectations(t)
   921  
   922  }
   923  
   924  // TestPrepareProposalErrorOnTooManyTxs tests that the block creation logic returns
   925  // an error if the ResponsePrepareProposal returned from the application is invalid.
   926  func TestPrepareProposalErrorOnTooManyTxs(t *testing.T) {
   927  	const height = 2
   928  	ctx, cancel := context.WithCancel(context.Background())
   929  	defer cancel()
   930  
   931  	logger := log.NewNopLogger()
   932  	eventBus := eventbus.NewDefault(logger)
   933  	require.NoError(t, eventBus.Start(ctx))
   934  
   935  	state, stateDB, privVals := makeState(t, 1, height)
   936  	// limit max block size
   937  	state.ConsensusParams.Block.MaxBytes = 60 * 1024
   938  	stateStore := sm.NewStore(stateDB)
   939  
   940  	evpool := &mocks.EvidencePool{}
   941  	evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0))
   942  
   943  	const nValidators = 1
   944  	var bytesPerTx int64 = 3
   945  	maxDataBytes := types.MaxDataBytes(state.ConsensusParams.Block.MaxBytes, 0, nValidators)
   946  	txs := factory.MakeNTxs(height, maxDataBytes/bytesPerTx+2) // +2 so that tx don't fit
   947  	mp := &mpmocks.Mempool{}
   948  	mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs))
   949  
   950  	trs := txsToTxRecords(types.Txs(txs))
   951  
   952  	app := abcimocks.NewApplication(t)
   953  	app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{
   954  		TxRecords: trs,
   955  	}, nil)
   956  
   957  	cc := abciclient.NewLocalClient(logger, app)
   958  	proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
   959  	err := proxyApp.Start(ctx)
   960  	require.NoError(t, err)
   961  
   962  	blockExec := sm.NewBlockExecutor(
   963  		stateStore,
   964  		logger,
   965  		proxyApp,
   966  		mp,
   967  		evpool,
   968  		nil,
   969  		eventBus,
   970  		sm.NopMetrics(),
   971  	)
   972  	pa, _ := state.Validators.GetByIndex(0)
   973  	commit, _ := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
   974  	block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa)
   975  	require.ErrorContains(t, err, "transaction data size exceeds maximum")
   976  	require.Nil(t, block, "")
   977  
   978  	mp.AssertExpectations(t)
   979  }
   980  
   981  // TestPrepareProposalErrorOnPrepareProposalError tests when the client returns an error
   982  // upon calling PrepareProposal on it.
   983  func TestPrepareProposalErrorOnPrepareProposalError(t *testing.T) {
   984  	const height = 2
   985  	ctx, cancel := context.WithCancel(context.Background())
   986  	defer cancel()
   987  
   988  	logger := log.NewNopLogger()
   989  	eventBus := eventbus.NewDefault(logger)
   990  	require.NoError(t, eventBus.Start(ctx))
   991  
   992  	state, stateDB, privVals := makeState(t, 1, height)
   993  	stateStore := sm.NewStore(stateDB)
   994  
   995  	evpool := &mocks.EvidencePool{}
   996  	evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0))
   997  
   998  	txs := factory.MakeNTxs(height, 10)
   999  	mp := &mpmocks.Mempool{}
  1000  	mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs))
  1001  
  1002  	cm := &abciclientmocks.Client{}
  1003  	cm.On("IsRunning").Return(true)
  1004  	cm.On("Error").Return(nil)
  1005  	cm.On("Start", mock.Anything).Return(nil).Once()
  1006  	cm.On("Wait").Return(nil).Once()
  1007  	cm.On("Stop").Return(nil).Once()
  1008  	cm.On("PrepareProposal", mock.Anything, mock.Anything).Return(nil, errors.New("an injected error")).Once()
  1009  
  1010  	proxyApp := proxy.New(cm, logger, proxy.NopMetrics())
  1011  	err := proxyApp.Start(ctx)
  1012  	require.NoError(t, err)
  1013  
  1014  	blockExec := sm.NewBlockExecutor(
  1015  		stateStore,
  1016  		logger,
  1017  		proxyApp,
  1018  		mp,
  1019  		evpool,
  1020  		nil,
  1021  		eventBus,
  1022  		sm.NopMetrics(),
  1023  	)
  1024  	pa, _ := state.Validators.GetByIndex(0)
  1025  	commit, _ := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
  1026  	block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa)
  1027  	require.Nil(t, block)
  1028  	require.ErrorContains(t, err, "an injected error")
  1029  
  1030  	mp.AssertExpectations(t)
  1031  }
  1032  
  1033  // TestCreateProposalBlockPanicOnAbsentVoteExtensions ensures that the CreateProposalBlock
  1034  // call correctly panics when the vote extension data is missing from the extended commit
  1035  // data that the method receives.
  1036  func TestCreateProposalAbsentVoteExtensions(t *testing.T) {
  1037  	for _, testCase := range []struct {
  1038  		name string
  1039  
  1040  		// The height that is about to be proposed
  1041  		height int64
  1042  
  1043  		// The first height during which vote extensions will be required for consensus to proceed.
  1044  		extensionEnableHeight int64
  1045  		expectPanic           bool
  1046  	}{
  1047  		{
  1048  			name:                  "missing extension data on first required height",
  1049  			height:                2,
  1050  			extensionEnableHeight: 1,
  1051  			expectPanic:           true,
  1052  		},
  1053  		{
  1054  			name:                  "missing extension during before required height",
  1055  			height:                2,
  1056  			extensionEnableHeight: 2,
  1057  			expectPanic:           false,
  1058  		},
  1059  		{
  1060  			name:                  "missing extension data and not required",
  1061  			height:                2,
  1062  			extensionEnableHeight: 0,
  1063  			expectPanic:           false,
  1064  		},
  1065  		{
  1066  			name:                  "missing extension data and required in two heights",
  1067  			height:                2,
  1068  			extensionEnableHeight: 3,
  1069  			expectPanic:           false,
  1070  		},
  1071  	} {
  1072  		t.Run(testCase.name, func(t *testing.T) {
  1073  			ctx, cancel := context.WithCancel(context.Background())
  1074  			defer cancel()
  1075  
  1076  			logger := log.NewNopLogger()
  1077  
  1078  			eventBus := eventbus.NewDefault(logger)
  1079  			require.NoError(t, eventBus.Start(ctx))
  1080  
  1081  			app := abcimocks.NewApplication(t)
  1082  			if !testCase.expectPanic {
  1083  				app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{}, nil)
  1084  			}
  1085  			cc := abciclient.NewLocalClient(logger, app)
  1086  			proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
  1087  			err := proxyApp.Start(ctx)
  1088  			require.NoError(t, err)
  1089  
  1090  			state, stateDB, privVals := makeState(t, 1, int(testCase.height-1))
  1091  			stateStore := sm.NewStore(stateDB)
  1092  			state.ConsensusParams.ABCI.VoteExtensionsEnableHeight = testCase.extensionEnableHeight
  1093  			mp := &mpmocks.Mempool{}
  1094  			mp.On("Lock").Return()
  1095  			mp.On("Unlock").Return()
  1096  			mp.On("FlushAppConn", mock.Anything).Return(nil)
  1097  			mp.On("Update",
  1098  				mock.Anything,
  1099  				mock.Anything,
  1100  				mock.Anything,
  1101  				mock.Anything,
  1102  				mock.Anything,
  1103  				mock.Anything).Return(nil)
  1104  			mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs{})
  1105  
  1106  			blockExec := sm.NewBlockExecutor(
  1107  				stateStore,
  1108  				logger,
  1109  				proxyApp,
  1110  				mp,
  1111  				sm.EmptyEvidencePool{},
  1112  				nil,
  1113  				eventBus,
  1114  				sm.NopMetrics(),
  1115  			)
  1116  			block := sf.MakeBlock(state, testCase.height, new(types.Commit))
  1117  			bps, err := block.MakePartSet(testPartSize)
  1118  			require.NoError(t, err)
  1119  			blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
  1120  			pa, _ := state.Validators.GetByIndex(0)
  1121  			lastCommit, _ := makeValidCommit(ctx, t, testCase.height-1, blockID, state.Validators, privVals)
  1122  			stripSignatures(lastCommit)
  1123  			if testCase.expectPanic {
  1124  				require.Panics(t, func() {
  1125  					blockExec.CreateProposalBlock(ctx, testCase.height, state, lastCommit, pa) //nolint:errcheck
  1126  				})
  1127  			} else {
  1128  				_, err = blockExec.CreateProposalBlock(ctx, testCase.height, state, lastCommit, pa)
  1129  				require.NoError(t, err)
  1130  			}
  1131  		})
  1132  	}
  1133  }
  1134  
  1135  func stripSignatures(ec *types.ExtendedCommit) {
  1136  	for i, commitSig := range ec.ExtendedSignatures {
  1137  		commitSig.Extension = nil
  1138  		commitSig.ExtensionSignature = nil
  1139  		ec.ExtendedSignatures[i] = commitSig
  1140  	}
  1141  }
  1142  
  1143  func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) types.BlockID {
  1144  	var (
  1145  		h   = make([]byte, crypto.HashSize)
  1146  		psH = make([]byte, crypto.HashSize)
  1147  	)
  1148  	copy(h, hash)
  1149  	copy(psH, partSetHash)
  1150  	return types.BlockID{
  1151  		Hash: h,
  1152  		PartSetHeader: types.PartSetHeader{
  1153  			Total: partSetSize,
  1154  			Hash:  psH,
  1155  		},
  1156  	}
  1157  }
  1158  
  1159  func txsToTxRecords(txs []types.Tx) []*abci.TxRecord {
  1160  	trs := make([]*abci.TxRecord, len(txs))
  1161  	for i, tx := range txs {
  1162  		trs[i] = &abci.TxRecord{
  1163  			Action: abci.TxRecord_UNMODIFIED,
  1164  			Tx:     tx,
  1165  		}
  1166  	}
  1167  	return trs
  1168  }