github.com/Finschia/ostracon@v1.1.5/state/execution_test.go (about)

     1  package state_test
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/mock"
    10  	"github.com/stretchr/testify/require"
    11  
    12  	abci "github.com/tendermint/tendermint/abci/types"
    13  	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
    14  	tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
    15  
    16  	"github.com/Finschia/ostracon/crypto"
    17  	"github.com/Finschia/ostracon/crypto/ed25519"
    18  	cryptoenc "github.com/Finschia/ostracon/crypto/encoding"
    19  	"github.com/Finschia/ostracon/crypto/tmhash"
    20  	"github.com/Finschia/ostracon/libs/bytes"
    21  	"github.com/Finschia/ostracon/libs/log"
    22  	mmock "github.com/Finschia/ostracon/mempool/mock"
    23  	"github.com/Finschia/ostracon/proxy"
    24  	sm "github.com/Finschia/ostracon/state"
    25  	"github.com/Finschia/ostracon/state/mocks"
    26  	"github.com/Finschia/ostracon/types"
    27  	tmtime "github.com/Finschia/ostracon/types/time"
    28  	"github.com/Finschia/ostracon/version"
    29  )
    30  
    31  var (
    32  	chainID             = "execution_chain"
    33  	testPartSize uint32 = 65536
    34  	nTxsPerBlock        = 10
    35  )
    36  
    37  func TestApplyBlock(t *testing.T) {
    38  	app := &testApp{}
    39  	cc := proxy.NewLocalClientCreator(app)
    40  	proxyApp := proxy.NewAppConns(cc)
    41  	err := proxyApp.Start()
    42  	require.Nil(t, err)
    43  	defer proxyApp.Stop() //nolint:errcheck // ignore for tests
    44  
    45  	state, stateDB, privVals := makeState(1, 1)
    46  	stateStore := sm.NewStore(stateDB, sm.StoreOptions{
    47  		DiscardABCIResponses: false,
    48  	})
    49  
    50  	blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(),
    51  		mmock.Mempool{}, sm.EmptyEvidencePool{})
    52  
    53  	block := makeBlockWithPrivVal(state, privVals[state.Validators.Validators[0].Address.String()], 1)
    54  	blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()}
    55  
    56  	state, retainHeight, err := blockExec.ApplyBlock(state, blockID, block, nil)
    57  	require.Nil(t, err)
    58  	assert.EqualValues(t, retainHeight, 1)
    59  
    60  	// TODO check state and mempool
    61  	assert.EqualValues(t, TestAppVersion, state.Version.Consensus.App, "App version wasn't updated")
    62  }
    63  
    64  // TestBeginBlockValidators ensures we send absent validators list.
    65  func TestBeginBlockValidators(t *testing.T) {
    66  	app := &testApp{}
    67  	cc := proxy.NewLocalClientCreator(app)
    68  	proxyApp := proxy.NewAppConns(cc)
    69  	err := proxyApp.Start()
    70  	require.Nil(t, err)
    71  	defer proxyApp.Stop() //nolint:errcheck // no need to check error again
    72  
    73  	state, stateDB, privVals := makeState(2, 2)
    74  	stateStore := sm.NewStore(stateDB, sm.StoreOptions{
    75  		DiscardABCIResponses: false,
    76  	})
    77  
    78  	prevHash := state.LastBlockID.Hash
    79  	prevParts := types.PartSetHeader{}
    80  	prevBlockID := types.BlockID{Hash: prevHash, PartSetHeader: prevParts}
    81  
    82  	var (
    83  		now        = tmtime.Now()
    84  		commitSig0 = types.NewCommitSigForBlock(
    85  			[]byte("Signature1"),
    86  			state.Validators.Validators[0].Address,
    87  			now)
    88  		commitSig1 = types.NewCommitSigForBlock(
    89  			[]byte("Signature2"),
    90  			state.Validators.Validators[1].Address,
    91  			now)
    92  		absentSig = types.NewCommitSigAbsent()
    93  	)
    94  
    95  	testCases := []struct {
    96  		desc                     string
    97  		lastCommitSigs           []types.CommitSig
    98  		expectedAbsentValidators []int
    99  	}{
   100  		{"none absent", []types.CommitSig{commitSig0, commitSig1}, []int{}},
   101  		{"one absent", []types.CommitSig{commitSig0, absentSig}, []int{1}},
   102  		{"multiple absent", []types.CommitSig{absentSig, absentSig}, []int{0, 1}},
   103  	}
   104  
   105  	for _, tc := range testCases {
   106  		lastCommit := types.NewCommit(1, 0, prevBlockID, tc.lastCommitSigs)
   107  
   108  		proposer := state.Validators.SelectProposer(state.LastProofHash, 1, 0)
   109  		message := state.MakeHashMessage(0)
   110  		proof, _ := privVals[proposer.Address.String()].GenerateVRFProof(message)
   111  
   112  		// block for height 2
   113  		block, _ := state.MakeBlock(2, makeTxs(2), lastCommit, nil, proposer.Address, 0, proof)
   114  
   115  		_, err = sm.ExecCommitBlock(proxyApp.Consensus(), block, log.TestingLogger(), stateStore, 1)
   116  		require.Nil(t, err, tc.desc)
   117  
   118  		// -> app receives a list of validators with a bool indicating if they signed
   119  		ctr := 0
   120  		for i, v := range app.CommitVotes {
   121  			if ctr < len(tc.expectedAbsentValidators) &&
   122  				tc.expectedAbsentValidators[ctr] == i {
   123  
   124  				assert.False(t, v.SignedLastBlock)
   125  				ctr++
   126  			} else {
   127  				assert.True(t, v.SignedLastBlock)
   128  			}
   129  		}
   130  	}
   131  }
   132  
   133  // TestBeginBlockByzantineValidators ensures we send byzantine validators list.
   134  func TestBeginBlockByzantineValidators(t *testing.T) {
   135  	app := &testApp{}
   136  	cc := proxy.NewLocalClientCreator(app)
   137  	proxyApp := proxy.NewAppConns(cc)
   138  	err := proxyApp.Start()
   139  	require.Nil(t, err)
   140  	defer proxyApp.Stop() //nolint:errcheck // ignore for tests
   141  
   142  	state, stateDB, privVals := makeState(2, 12)
   143  	stateStore := sm.NewStore(stateDB, sm.StoreOptions{
   144  		DiscardABCIResponses: false,
   145  	})
   146  
   147  	defaultEvidenceTime := time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
   148  	privVal := privVals[state.Validators.Validators[0].Address.String()]
   149  	blockID := makeBlockID([]byte("headerhash"), 1000, []byte("partshash"))
   150  	header := &types.Header{
   151  		Version:            tmversion.Consensus{Block: version.BlockProtocol, App: version.AppProtocol},
   152  		ChainID:            state.ChainID,
   153  		Height:             10,
   154  		Time:               defaultEvidenceTime,
   155  		LastBlockID:        blockID,
   156  		LastCommitHash:     crypto.CRandBytes(tmhash.Size),
   157  		DataHash:           crypto.CRandBytes(tmhash.Size),
   158  		ValidatorsHash:     state.Validators.Hash(),
   159  		NextValidatorsHash: state.Validators.Hash(),
   160  		ConsensusHash:      crypto.CRandBytes(tmhash.Size),
   161  		AppHash:            crypto.CRandBytes(tmhash.Size),
   162  		LastResultsHash:    crypto.CRandBytes(tmhash.Size),
   163  		EvidenceHash:       crypto.CRandBytes(tmhash.Size),
   164  		ProposerAddress:    crypto.CRandBytes(crypto.AddressSize),
   165  	}
   166  
   167  	// we don't need to worry about validating the evidence as long as they pass validate basic
   168  	dve := types.NewMockDuplicateVoteEvidenceWithValidator(3, defaultEvidenceTime, privVal, state.ChainID)
   169  	dve.ValidatorPower = 1000
   170  	lcae := &types.LightClientAttackEvidence{
   171  		ConflictingBlock: &types.LightBlock{
   172  			SignedHeader: &types.SignedHeader{
   173  				Header: header,
   174  				Commit: types.NewCommit(10, 0, makeBlockID(header.Hash(), 100, []byte("partshash")), []types.CommitSig{{
   175  					BlockIDFlag:      types.BlockIDFlagNil,
   176  					ValidatorAddress: crypto.AddressHash([]byte("validator_address")),
   177  					Timestamp:        defaultEvidenceTime,
   178  					Signature:        crypto.CRandBytes(types.MaxSignatureSize),
   179  				}}),
   180  			},
   181  			ValidatorSet: state.Validators,
   182  		},
   183  		CommonHeight:        8,
   184  		ByzantineValidators: []*types.Validator{state.Validators.Validators[0]},
   185  		TotalVotingPower:    12,
   186  		Timestamp:           defaultEvidenceTime,
   187  	}
   188  
   189  	ev := []types.Evidence{dve, lcae}
   190  
   191  	abciEv := []abci.Evidence{
   192  		{
   193  			Type:             abci.EvidenceType_DUPLICATE_VOTE,
   194  			Height:           3,
   195  			Time:             defaultEvidenceTime,
   196  			Validator:        types.OC2PB.Validator(state.Validators.Validators[0]),
   197  			TotalVotingPower: 10,
   198  		},
   199  		{
   200  			Type:             abci.EvidenceType_LIGHT_CLIENT_ATTACK,
   201  			Height:           8,
   202  			Time:             defaultEvidenceTime,
   203  			Validator:        types.OC2PB.Validator(state.Validators.Validators[0]),
   204  			TotalVotingPower: 12,
   205  		},
   206  	}
   207  
   208  	evpool := &mocks.EvidencePool{}
   209  	evpool.On("PendingEvidence", mock.AnythingOfType("int64")).Return(ev, int64(100))
   210  	evpool.On("Update", mock.AnythingOfType("state.State"), mock.AnythingOfType("types.EvidenceList")).Return()
   211  	evpool.On("CheckEvidence", mock.AnythingOfType("types.EvidenceList")).Return(nil)
   212  
   213  	blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(),
   214  		mmock.Mempool{}, evpool)
   215  
   216  	now := tmtime.Now()
   217  	state.LastBlockID = blockID
   218  	state.LastBlockTime = now.Add(-1 * time.Second)
   219  
   220  	prevHash := state.LastBlockID.Hash
   221  	prevParts := types.PartSetHeader{}
   222  	prevBlockID := types.BlockID{Hash: prevHash, PartSetHeader: prevParts}
   223  
   224  	ev1 := types.DuplicateVoteEvidence{
   225  		VoteA:            &types.Vote{},
   226  		VoteB:            &types.Vote{},
   227  		TotalVotingPower: 100,
   228  		ValidatorPower:   10,
   229  		Timestamp:        time.Now(),
   230  	}
   231  	ev2 := types.LightClientAttackEvidence{}
   232  
   233  	testCases := []struct {
   234  		desc                        string
   235  		evidence                    []types.Evidence
   236  		expectedByzantineValidators []abci.Evidence
   237  	}{
   238  		{"none byzantine", []types.Evidence{}, []abci.Evidence{}},
   239  		{"one byzantine", []types.Evidence{&ev1}, ev1.ABCI()},
   240  		{"multiple byzantine", []types.Evidence{&ev1, &ev2}, append(ev1.ABCI(), ev2.ABCI()...)},
   241  	}
   242  
   243  	var (
   244  		commitSig0 = types.NewCommitSigForBlock(
   245  			[]byte("Signature1"),
   246  			state.Validators.Validators[0].Address,
   247  			now)
   248  		commitSig1 = types.NewCommitSigForBlock(
   249  			[]byte("Signature2"),
   250  			state.Validators.Validators[1].Address,
   251  			now)
   252  	)
   253  	commitSigs := []types.CommitSig{commitSig0, commitSig1}
   254  	lastCommit := types.NewCommit(9, 0, prevBlockID, commitSigs)
   255  	for _, tc := range testCases {
   256  		message := state.MakeHashMessage(0)
   257  		proposer := state.Validators.SelectProposer(state.LastProofHash, 1, 0)
   258  		proof, _ := privVals[proposer.Address.String()].GenerateVRFProof(message)
   259  		block, _ := state.MakeBlock(10, makeTxs(2), lastCommit, nil, proposer.Address, 0, proof)
   260  		block.Time = now
   261  		block.Evidence.Evidence = tc.evidence
   262  		_, err = sm.ExecCommitBlock(proxyApp.Consensus(), block, log.TestingLogger(), stateStore, 10)
   263  		require.Nil(t, err, tc.desc)
   264  	}
   265  
   266  	proposer := state.Validators.SelectProposer(state.LastProofHash, 12, 0)
   267  	privVal = privVals[proposer.Address.String()]
   268  
   269  	block := makeBlockWithPrivVal(state, privVal, 12)
   270  	block.Evidence = types.EvidenceData{Evidence: ev}
   271  	block.Header.EvidenceHash = block.Evidence.Hash()
   272  	blockID = types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()}
   273  	block.LastCommit, _ = makeValidCommit(11, state.LastBlockID, state.Validators, privVals)
   274  	block.LastCommitHash = block.LastCommit.Hash()
   275  	block.Time = sm.MedianTime(block.LastCommit, state.LastValidators)
   276  	message := state.MakeHashMessage(block.Round)
   277  	proof, _ := privVal.GenerateVRFProof(message)
   278  	block.Proof = bytes.HexBytes(proof)
   279  
   280  	state, retainHeight, err := blockExec.ApplyBlock(state, blockID, block, nil)
   281  	require.Nil(t, err)
   282  	assert.EqualValues(t, retainHeight, 1)
   283  
   284  	// TODO check state and mempool
   285  	assert.Equal(t, abciEv, app.ByzantineValidators)
   286  }
   287  
   288  func TestValidateValidatorUpdates(t *testing.T) {
   289  	pubkey1 := ed25519.GenPrivKey().PubKey()
   290  	pubkey2 := ed25519.GenPrivKey().PubKey()
   291  	pk1, err := cryptoenc.PubKeyToProto(pubkey1)
   292  	assert.NoError(t, err)
   293  	pk2, err := cryptoenc.PubKeyToProto(pubkey2)
   294  	assert.NoError(t, err)
   295  
   296  	defaultValidatorParams := tmproto.ValidatorParams{PubKeyTypes: []string{types.ABCIPubKeyTypeEd25519}}
   297  
   298  	testCases := []struct {
   299  		name string
   300  
   301  		abciUpdates     []abci.ValidatorUpdate
   302  		validatorParams tmproto.ValidatorParams
   303  
   304  		shouldErr bool
   305  	}{
   306  		{
   307  			"adding a validator is OK",
   308  			[]abci.ValidatorUpdate{{PubKey: pk2, Power: 20}},
   309  			defaultValidatorParams,
   310  			false,
   311  		},
   312  		{
   313  			"updating a validator is OK",
   314  			[]abci.ValidatorUpdate{{PubKey: pk1, Power: 20}},
   315  			defaultValidatorParams,
   316  			false,
   317  		},
   318  		{
   319  			"removing a validator is OK",
   320  			[]abci.ValidatorUpdate{{PubKey: pk2, Power: 0}},
   321  			defaultValidatorParams,
   322  			false,
   323  		},
   324  		{
   325  			"adding a validator with negative power results in error",
   326  			[]abci.ValidatorUpdate{{PubKey: pk2, Power: -100}},
   327  			defaultValidatorParams,
   328  			true,
   329  		},
   330  	}
   331  
   332  	for _, tc := range testCases {
   333  		tc := tc
   334  		t.Run(tc.name, func(t *testing.T) {
   335  			err := sm.ValidateValidatorUpdates(tc.abciUpdates, tc.validatorParams)
   336  			if tc.shouldErr {
   337  				assert.Error(t, err)
   338  			} else {
   339  				assert.NoError(t, err)
   340  			}
   341  		})
   342  	}
   343  }
   344  
   345  func TestUpdateValidators(t *testing.T) {
   346  	pubkey1 := ed25519.GenPrivKey().PubKey()
   347  	val1 := types.NewValidator(pubkey1, 10)
   348  	pubkey2 := ed25519.GenPrivKey().PubKey()
   349  	val2 := types.NewValidator(pubkey2, 20)
   350  
   351  	pk, err := cryptoenc.PubKeyToProto(pubkey1)
   352  	require.NoError(t, err)
   353  	pk2, err := cryptoenc.PubKeyToProto(pubkey2)
   354  	require.NoError(t, err)
   355  
   356  	testCases := []struct {
   357  		name string
   358  
   359  		currentSet  *types.ValidatorSet
   360  		abciUpdates []abci.ValidatorUpdate
   361  
   362  		resultingSet *types.ValidatorSet
   363  		shouldErr    bool
   364  	}{
   365  		{
   366  			"adding a validator is OK",
   367  			types.NewValidatorSet([]*types.Validator{val1}),
   368  			[]abci.ValidatorUpdate{{PubKey: pk2, Power: 20}},
   369  			types.NewValidatorSet([]*types.Validator{val1, val2}),
   370  			false,
   371  		},
   372  		{
   373  			"updating a validator is OK",
   374  			types.NewValidatorSet([]*types.Validator{val1}),
   375  			[]abci.ValidatorUpdate{{PubKey: pk, Power: 20}},
   376  			types.NewValidatorSet([]*types.Validator{types.NewValidator(pubkey1, 20)}),
   377  			false,
   378  		},
   379  		{
   380  			"removing a validator is OK",
   381  			types.NewValidatorSet([]*types.Validator{val1, val2}),
   382  			[]abci.ValidatorUpdate{{PubKey: pk2, Power: 0}},
   383  			types.NewValidatorSet([]*types.Validator{val1}),
   384  			false,
   385  		},
   386  		{
   387  			"removing a non-existing validator results in error",
   388  			types.NewValidatorSet([]*types.Validator{val1}),
   389  			[]abci.ValidatorUpdate{{PubKey: pk2, Power: 0}},
   390  			types.NewValidatorSet([]*types.Validator{val1}),
   391  			true,
   392  		},
   393  	}
   394  
   395  	for _, tc := range testCases {
   396  		tc := tc
   397  		t.Run(tc.name, func(t *testing.T) {
   398  			updates, err := types.PB2OC.ValidatorUpdates(tc.abciUpdates)
   399  			assert.NoError(t, err)
   400  			err = tc.currentSet.UpdateWithChangeSet(updates)
   401  			if tc.shouldErr {
   402  				assert.Error(t, err)
   403  			} else {
   404  				assert.NoError(t, err)
   405  				require.Equal(t, tc.resultingSet.Size(), tc.currentSet.Size())
   406  
   407  				assert.Equal(t, tc.resultingSet.TotalVotingPower(), tc.currentSet.TotalVotingPower())
   408  
   409  				assert.Equal(t, tc.resultingSet.Validators[0].Address, tc.currentSet.Validators[0].Address)
   410  				if tc.resultingSet.Size() > 1 {
   411  					assert.Equal(t, tc.resultingSet.Validators[1].Address, tc.currentSet.Validators[1].Address)
   412  				}
   413  			}
   414  		})
   415  	}
   416  }
   417  
   418  // TestEndBlockValidatorUpdates ensures we update validator set and send an event.
   419  func TestEndBlockValidatorUpdates(t *testing.T) {
   420  	app := &testApp{}
   421  	cc := proxy.NewLocalClientCreator(app)
   422  	proxyApp := proxy.NewAppConns(cc)
   423  	err := proxyApp.Start()
   424  	require.Nil(t, err)
   425  	defer proxyApp.Stop() //nolint:errcheck // ignore for tests
   426  
   427  	state, stateDB, privVals := makeState(1, 1)
   428  	stateStore := sm.NewStore(stateDB, sm.StoreOptions{
   429  		DiscardABCIResponses: false,
   430  	})
   431  
   432  	blockExec := sm.NewBlockExecutor(
   433  		stateStore,
   434  		log.TestingLogger(),
   435  		proxyApp.Consensus(),
   436  		mmock.Mempool{},
   437  		sm.EmptyEvidencePool{},
   438  	)
   439  
   440  	eventBus := types.NewEventBus()
   441  	err = eventBus.Start()
   442  	require.NoError(t, err)
   443  	defer eventBus.Stop() //nolint:errcheck // ignore for tests
   444  
   445  	blockExec.SetEventBus(eventBus)
   446  
   447  	updatesSub, err := eventBus.Subscribe(
   448  		context.Background(),
   449  		"TestEndBlockValidatorUpdates",
   450  		types.EventQueryValidatorSetUpdates,
   451  	)
   452  	require.NoError(t, err)
   453  
   454  	block := makeBlockWithPrivVal(state, privVals[state.Validators.Validators[0].Address.String()], 1)
   455  	blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()}
   456  
   457  	pubkey := ed25519.GenPrivKey().PubKey()
   458  	pk, err := cryptoenc.PubKeyToProto(pubkey)
   459  	require.NoError(t, err)
   460  	app.ValidatorUpdates = []abci.ValidatorUpdate{
   461  		{PubKey: pk, Power: 10},
   462  	}
   463  
   464  	state, _, err = blockExec.ApplyBlock(state, blockID, block, nil)
   465  	require.Nil(t, err)
   466  	// test new validator was added to NextValidators
   467  	if assert.Equal(t, state.Validators.Size()+1, state.NextValidators.Size()) {
   468  		idx, _ := state.NextValidators.GetByAddress(pubkey.Address())
   469  		if idx < 0 {
   470  			t.Fatalf("can't find address %v in the set %v", pubkey.Address(), state.NextValidators)
   471  		}
   472  	}
   473  
   474  	// test we threw an event
   475  	select {
   476  	case msg := <-updatesSub.Out():
   477  		event, ok := msg.Data().(types.EventDataValidatorSetUpdates)
   478  		require.True(t, ok, "Expected event of type EventDataValidatorSetUpdates, got %T", msg.Data())
   479  		if assert.NotEmpty(t, event.ValidatorUpdates) {
   480  			assert.Equal(t, pubkey, event.ValidatorUpdates[0].PubKey)
   481  			assert.EqualValues(t, 10, event.ValidatorUpdates[0].VotingPower)
   482  		}
   483  	case <-updatesSub.Cancelled():
   484  		t.Fatalf("updatesSub was cancelled (reason: %v)", updatesSub.Err())
   485  	case <-time.After(1 * time.Second):
   486  		t.Fatal("Did not receive EventValidatorSetUpdates within 1 sec.")
   487  	}
   488  }
   489  
   490  // TestEndBlockValidatorUpdatesResultingInEmptySet checks that processing validator updates that
   491  // would result in empty set causes no panic, an error is raised and NextValidators is not updated
   492  func TestEndBlockValidatorUpdatesResultingInEmptySet(t *testing.T) {
   493  	app := &testApp{}
   494  	cc := proxy.NewLocalClientCreator(app)
   495  	proxyApp := proxy.NewAppConns(cc)
   496  	err := proxyApp.Start()
   497  	require.Nil(t, err)
   498  	defer proxyApp.Stop() //nolint:errcheck // ignore for tests
   499  
   500  	state, stateDB, _ := makeState(1, 1)
   501  	stateStore := sm.NewStore(stateDB, sm.StoreOptions{
   502  		DiscardABCIResponses: false,
   503  	})
   504  	blockExec := sm.NewBlockExecutor(
   505  		stateStore,
   506  		log.TestingLogger(),
   507  		proxyApp.Consensus(),
   508  		mmock.Mempool{},
   509  		sm.EmptyEvidencePool{},
   510  	)
   511  
   512  	block := makeBlock(state, 1)
   513  	blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()}
   514  
   515  	vp, err := cryptoenc.PubKeyToProto(state.Validators.Validators[0].PubKey)
   516  	require.NoError(t, err)
   517  	// Remove the only validator
   518  	app.ValidatorUpdates = []abci.ValidatorUpdate{
   519  		{PubKey: vp, Power: 0},
   520  	}
   521  
   522  	assert.NotPanics(t, func() { state, _, err = blockExec.ApplyBlock(state, blockID, block, nil) })
   523  	assert.NotNil(t, err)
   524  	assert.NotEmpty(t, state.NextValidators.Validators)
   525  }
   526  
   527  func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) types.BlockID {
   528  	var (
   529  		h   = make([]byte, tmhash.Size)
   530  		psH = make([]byte, tmhash.Size)
   531  	)
   532  	copy(h, hash)
   533  	copy(psH, partSetHash)
   534  	return types.BlockID{
   535  		Hash: h,
   536  		PartSetHeader: types.PartSetHeader{
   537  			Total: partSetSize,
   538  			Hash:  psH,
   539  		},
   540  	}
   541  }