github.com/okex/exchain@v1.8.0/libs/tendermint/consensus/reactor_test.go (about)

     1  package consensus
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"path"
     8  	"runtime"
     9  	"runtime/pprof"
    10  	"sync"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  
    17  	dbm "github.com/okex/exchain/libs/tm-db"
    18  
    19  	abcicli "github.com/okex/exchain/libs/tendermint/abci/client"
    20  	"github.com/okex/exchain/libs/tendermint/abci/example/kvstore"
    21  	abci "github.com/okex/exchain/libs/tendermint/abci/types"
    22  	cfg "github.com/okex/exchain/libs/tendermint/config"
    23  	cstypes "github.com/okex/exchain/libs/tendermint/consensus/types"
    24  	"github.com/okex/exchain/libs/tendermint/crypto/tmhash"
    25  	"github.com/okex/exchain/libs/tendermint/libs/bits"
    26  	"github.com/okex/exchain/libs/tendermint/libs/bytes"
    27  	"github.com/okex/exchain/libs/tendermint/libs/log"
    28  	mempl "github.com/okex/exchain/libs/tendermint/mempool"
    29  	"github.com/okex/exchain/libs/tendermint/p2p"
    30  	"github.com/okex/exchain/libs/tendermint/p2p/mock"
    31  	sm "github.com/okex/exchain/libs/tendermint/state"
    32  	"github.com/okex/exchain/libs/tendermint/store"
    33  	"github.com/okex/exchain/libs/tendermint/types"
    34  )
    35  
    36  //----------------------------------------------
    37  // in-process testnets
    38  
    39  func startConsensusNet(t *testing.T, css []*State, n int) (
    40  	[]*Reactor,
    41  	[]types.Subscription,
    42  	[]*types.EventBus,
    43  ) {
    44  	reactors := make([]*Reactor, n)
    45  	blocksSubs := make([]types.Subscription, 0)
    46  	eventBuses := make([]*types.EventBus, n)
    47  	for i := 0; i < n; i++ {
    48  		/*logger, err := tmflags.ParseLogLevel("consensus:info,*:error", logger, "info")
    49  		if err != nil {	t.Fatal(err)}*/
    50  		reactors[i] = NewReactor(css[i], true, false) // so we dont start the consensus states
    51  		reactors[i].SetLogger(css[i].Logger)
    52  
    53  		// eventBus is already started with the cs
    54  		eventBuses[i] = css[i].eventBus
    55  		reactors[i].SetEventBus(eventBuses[i])
    56  
    57  		blocksSub, err := eventBuses[i].Subscribe(context.Background(), testSubscriber, types.EventQueryNewBlock)
    58  		require.NoError(t, err)
    59  		blocksSubs = append(blocksSubs, blocksSub)
    60  
    61  		if css[i].state.LastBlockHeight == 0 { //simulate handle initChain in handshake
    62  			sm.SaveState(css[i].blockExec.DB(), css[i].state)
    63  		}
    64  	}
    65  	// make connected switches and start all reactors
    66  	p2p.MakeConnectedSwitches(config.P2P, n, func(i int, s *p2p.Switch) *p2p.Switch {
    67  		s.AddReactor("CONSENSUS", reactors[i])
    68  		s.SetLogger(reactors[i].conS.Logger.With("module", "p2p"))
    69  		return s
    70  	}, p2p.Connect2Switches)
    71  
    72  	// now that everyone is connected,  start the state machines
    73  	// If we started the state machines before everyone was connected,
    74  	// we'd block when the cs fires NewBlockEvent and the peers are trying to start their reactors
    75  	// TODO: is this still true with new pubsub?
    76  	for i := 0; i < n; i++ {
    77  		s := reactors[i].conS.GetState()
    78  		reactors[i].SwitchToConsensus(s, 0)
    79  	}
    80  	return reactors, blocksSubs, eventBuses
    81  }
    82  
    83  func stopConsensusNet(logger log.Logger, reactors []*Reactor, eventBuses []*types.EventBus) {
    84  	logger.Info("stopConsensusNet", "n", len(reactors))
    85  	for i, r := range reactors {
    86  		logger.Info("stopConsensusNet: Stopping Reactor", "i", i)
    87  		r.Switch.Stop()
    88  	}
    89  	for i, b := range eventBuses {
    90  		logger.Info("stopConsensusNet: Stopping eventBus", "i", i)
    91  		b.Stop()
    92  	}
    93  	logger.Info("stopConsensusNet: DONE", "n", len(reactors))
    94  }
    95  
    96  // Ensure a testnet makes blocks
    97  func TestReactorBasic(t *testing.T) {
    98  	N := 4
    99  	css, cleanup := randConsensusNet(N, "consensus_reactor_test", newMockTickerFunc(true), newCounter)
   100  	defer cleanup()
   101  	reactors, blocksSubs, eventBuses := startConsensusNet(t, css, N)
   102  	defer stopConsensusNet(log.TestingLogger(), reactors, eventBuses)
   103  	// wait till everyone makes the first new block
   104  	timeoutWaitGroup(t, N, func(j int) {
   105  		<-blocksSubs[j].Out()
   106  	}, css)
   107  }
   108  
   109  // Ensure we can process blocks with evidence
   110  func TestReactorWithEvidence(t *testing.T) {
   111  	types.RegisterMockEvidences(cdc)
   112  	types.RegisterMockEvidences(types.GetCodec())
   113  
   114  	nValidators := 4
   115  	testName := "consensus_reactor_test"
   116  	tickerFunc := newMockTickerFunc(true)
   117  	appFunc := newCounter
   118  
   119  	// heed the advice from https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction
   120  	// to unroll unwieldy abstractions. Here we duplicate the code from:
   121  	// css := randConsensusNet(N, "consensus_reactor_test", newMockTickerFunc(true), newCounter)
   122  
   123  	genDoc, privVals := randGenesisDoc(nValidators, false, 30)
   124  	css := make([]*State, nValidators)
   125  	logger := consensusLogger()
   126  	for i := 0; i < nValidators; i++ {
   127  		stateDB := dbm.NewMemDB() // each state needs its own db
   128  		state, _ := sm.LoadStateFromDBOrGenesisDoc(stateDB, genDoc)
   129  		thisConfig := ResetConfig(fmt.Sprintf("%s_%d", testName, i))
   130  		defer os.RemoveAll(thisConfig.RootDir)
   131  		ensureDir(path.Dir(thisConfig.Consensus.WalFile()), 0700) // dir for wal
   132  		app := appFunc()
   133  		vals := types.TM2PB.ValidatorUpdates(state.Validators)
   134  		app.InitChain(abci.RequestInitChain{Validators: vals})
   135  
   136  		pv := privVals[i]
   137  		// duplicate code from:
   138  		// css[i] = newStateWithConfig(thisConfig, state, privVals[i], app)
   139  
   140  		blockDB := dbm.NewMemDB()
   141  		blockStore := store.NewBlockStore(blockDB)
   142  
   143  		// one for mempool, one for consensus
   144  		mtx := new(sync.Mutex)
   145  		proxyAppConnMem := abcicli.NewLocalClient(mtx, app)
   146  		proxyAppConnCon := abcicli.NewLocalClient(mtx, app)
   147  
   148  		// Make Mempool
   149  		mempool := mempl.NewCListMempool(thisConfig.Mempool, proxyAppConnMem, 0)
   150  		mempool.SetLogger(log.TestingLogger().With("module", "mempool"))
   151  		if thisConfig.Consensus.WaitForTxs() {
   152  			mempool.EnableTxsAvailable()
   153  		}
   154  
   155  		// mock the evidence pool
   156  		// everyone includes evidence of another double signing
   157  		vIdx := (i + 1) % nValidators
   158  		pubKey, err := privVals[vIdx].GetPubKey()
   159  		require.NoError(t, err)
   160  		evpool := newMockEvidencePool(pubKey.Address())
   161  
   162  		// Make State
   163  		blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyAppConnCon, mempool, evpool)
   164  		cs := NewState(thisConfig.Consensus, state, blockExec, blockStore, mempool, evpool)
   165  		cs.SetLogger(log.TestingLogger().With("module", "consensus"))
   166  		cs.SetPrivValidator(pv)
   167  
   168  		eventBus := types.NewEventBus()
   169  		eventBus.SetLogger(log.TestingLogger().With("module", "events"))
   170  		eventBus.Start()
   171  		cs.SetEventBus(eventBus)
   172  
   173  		cs.SetTimeoutTicker(tickerFunc())
   174  		cs.SetLogger(logger.With("validator", i, "module", "consensus"))
   175  
   176  		css[i] = cs
   177  	}
   178  
   179  	reactors, blocksSubs, eventBuses := startConsensusNet(t, css, nValidators)
   180  	defer stopConsensusNet(log.TestingLogger(), reactors, eventBuses)
   181  
   182  	// wait till everyone makes the first new block with no evidence
   183  	timeoutWaitGroup(t, nValidators, func(j int) {
   184  		msg := <-blocksSubs[j].Out()
   185  		block := msg.Data().(types.EventDataNewBlock).Block
   186  		assert.True(t, len(block.Evidence.Evidence) == 0)
   187  	}, css)
   188  
   189  	// second block should have evidence
   190  	timeoutWaitGroup(t, nValidators, func(j int) {
   191  		msg := <-blocksSubs[j].Out()
   192  		block := msg.Data().(types.EventDataNewBlock).Block
   193  		assert.True(t, len(block.Evidence.Evidence) > 0)
   194  	}, css)
   195  }
   196  
   197  // mock evidence pool returns no evidence for block 1,
   198  // and returnes one piece for all higher blocks. The one piece
   199  // is for a given validator at block 1.
   200  type mockEvidencePool struct {
   201  	height int
   202  	ev     []types.Evidence
   203  }
   204  
   205  func newMockEvidencePool(val []byte) *mockEvidencePool {
   206  	return &mockEvidencePool{
   207  		ev: []types.Evidence{types.NewMockEvidence(1, time.Now().UTC(), 1, val)},
   208  	}
   209  }
   210  
   211  // NOTE: maxBytes is ignored
   212  func (m *mockEvidencePool) PendingEvidence(maxBytes int64) []types.Evidence {
   213  	if m.height > 0 {
   214  		return m.ev
   215  	}
   216  	return nil
   217  }
   218  func (m *mockEvidencePool) AddEvidence(types.Evidence) error { return nil }
   219  func (m *mockEvidencePool) Update(block *types.Block, state sm.State) {
   220  	if m.height > 0 {
   221  		if len(block.Evidence.Evidence) == 0 {
   222  			panic("block has no evidence")
   223  		}
   224  	}
   225  	m.height++
   226  }
   227  func (m *mockEvidencePool) IsCommitted(types.Evidence) bool { return false }
   228  
   229  //------------------------------------
   230  
   231  // Ensure a testnet makes blocks when there are txs
   232  func TestReactorCreatesBlockWhenEmptyBlocksFalse(t *testing.T) {
   233  	N := 4
   234  	css, cleanup := randConsensusNet(N, "consensus_reactor_test", newMockTickerFunc(true), newCounter,
   235  		func(c *cfg.Config) {
   236  			c.Consensus.CreateEmptyBlocks = false
   237  		})
   238  	defer cleanup()
   239  	reactors, blocksSubs, eventBuses := startConsensusNet(t, css, N)
   240  	defer stopConsensusNet(log.TestingLogger(), reactors, eventBuses)
   241  
   242  	// send a tx
   243  	if err := assertMempool(css[3].txNotifier).CheckTx([]byte{1, 2, 3}, nil, mempl.TxInfo{}); err != nil {
   244  		t.Error(err)
   245  	}
   246  
   247  	// wait till everyone makes the first new block
   248  	timeoutWaitGroup(t, N, func(j int) {
   249  		<-blocksSubs[j].Out()
   250  	}, css)
   251  }
   252  
   253  func TestReactorReceiveDoesNotPanicIfAddPeerHasntBeenCalledYet(t *testing.T) {
   254  	N := 1
   255  	css, cleanup := randConsensusNet(N, "consensus_reactor_test", newMockTickerFunc(true), newCounter)
   256  	defer cleanup()
   257  	reactors, _, eventBuses := startConsensusNet(t, css, N)
   258  	defer stopConsensusNet(log.TestingLogger(), reactors, eventBuses)
   259  
   260  	var (
   261  		reactor = reactors[0]
   262  		peer    = mock.NewPeer(nil)
   263  		msg     = cdc.MustMarshalBinaryBare(&HasVoteMessage{Height: 1, Round: 1, Index: 1, Type: types.PrevoteType})
   264  	)
   265  
   266  	reactor.InitPeer(peer)
   267  
   268  	// simulate switch calling Receive before AddPeer
   269  	assert.NotPanics(t, func() {
   270  		reactor.Receive(StateChannel, peer, msg)
   271  		reactor.AddPeer(peer)
   272  	})
   273  }
   274  
   275  func TestReactorReceivePanicsIfInitPeerHasntBeenCalledYet(t *testing.T) {
   276  	N := 1
   277  	css, cleanup := randConsensusNet(N, "consensus_reactor_test", newMockTickerFunc(true), newCounter)
   278  	defer cleanup()
   279  	reactors, _, eventBuses := startConsensusNet(t, css, N)
   280  	defer stopConsensusNet(log.TestingLogger(), reactors, eventBuses)
   281  
   282  	var (
   283  		reactor = reactors[0]
   284  		peer    = mock.NewPeer(nil)
   285  		msg     = cdc.MustMarshalBinaryBare(&HasVoteMessage{Height: 1, Round: 1, Index: 1, Type: types.PrevoteType})
   286  	)
   287  
   288  	// we should call InitPeer here
   289  
   290  	// simulate switch calling Receive before AddPeer
   291  	assert.Panics(t, func() {
   292  		reactor.Receive(StateChannel, peer, msg)
   293  	})
   294  }
   295  
   296  // Test we record stats about votes and block parts from other peers.
   297  func TestReactorRecordsVotesAndBlockParts(t *testing.T) {
   298  	N := 4
   299  	css, cleanup := randConsensusNet(N, "consensus_reactor_test", newMockTickerFunc(true), newCounter)
   300  	defer cleanup()
   301  	reactors, blocksSubs, eventBuses := startConsensusNet(t, css, N)
   302  	defer stopConsensusNet(log.TestingLogger(), reactors, eventBuses)
   303  
   304  	// wait till everyone makes the first new block
   305  	timeoutWaitGroup(t, N, func(j int) {
   306  		<-blocksSubs[j].Out()
   307  	}, css)
   308  
   309  	// Get peer
   310  	peer := reactors[1].Switch.Peers().List()[0]
   311  	// Get peer state
   312  	ps := peer.Get(types.PeerStateKey).(*PeerState)
   313  
   314  	assert.Equal(t, true, ps.VotesSent() > 0, "number of votes sent should have increased")
   315  	assert.Equal(t, true, ps.BlockPartsSent() > 0, "number of votes sent should have increased")
   316  }
   317  
   318  //-------------------------------------------------------------
   319  // ensure we can make blocks despite cycling a validator set
   320  
   321  func TestReactorVotingPowerChange(t *testing.T) {
   322  	nVals := 4
   323  	logger := log.TestingLogger()
   324  	css, cleanup := randConsensusNet(
   325  		nVals,
   326  		"consensus_voting_power_changes_test",
   327  		newMockTickerFunc(true),
   328  		newPersistentKVStore)
   329  	defer cleanup()
   330  	reactors, blocksSubs, eventBuses := startConsensusNet(t, css, nVals)
   331  	defer stopConsensusNet(logger, reactors, eventBuses)
   332  
   333  	// map of active validators
   334  	activeVals := make(map[string]struct{})
   335  	for i := 0; i < nVals; i++ {
   336  		pubKey, err := css[i].privValidator.GetPubKey()
   337  		require.NoError(t, err)
   338  		addr := pubKey.Address()
   339  		activeVals[string(addr)] = struct{}{}
   340  	}
   341  
   342  	// wait till everyone makes block 1
   343  	timeoutWaitGroup(t, nVals, func(j int) {
   344  		<-blocksSubs[j].Out()
   345  	}, css)
   346  
   347  	//---------------------------------------------------------------------------
   348  	logger.Debug("---------------------------- Testing changing the voting power of one validator a few times")
   349  
   350  	val1PubKey, err := css[0].privValidator.GetPubKey()
   351  	require.NoError(t, err)
   352  	val1PubKeyABCI := types.TM2PB.PubKey(val1PubKey)
   353  	updateValidatorTx := kvstore.MakeValSetChangeTx(val1PubKeyABCI, 25)
   354  	previousTotalVotingPower := css[0].GetRoundState().LastValidators.TotalVotingPower()
   355  
   356  	waitForAndValidateBlock(t, nVals, activeVals, blocksSubs, css, updateValidatorTx)
   357  	waitForAndValidateBlockWithTx(t, nVals, activeVals, blocksSubs, css, updateValidatorTx)
   358  	waitForAndValidateBlock(t, nVals, activeVals, blocksSubs, css)
   359  	waitForAndValidateBlock(t, nVals, activeVals, blocksSubs, css)
   360  
   361  	if css[0].GetRoundState().LastValidators.TotalVotingPower() == previousTotalVotingPower {
   362  		t.Fatalf(
   363  			"expected voting power to change (before: %d, after: %d)",
   364  			previousTotalVotingPower,
   365  			css[0].GetRoundState().LastValidators.TotalVotingPower())
   366  	}
   367  
   368  	updateValidatorTx = kvstore.MakeValSetChangeTx(val1PubKeyABCI, 2)
   369  	previousTotalVotingPower = css[0].GetRoundState().LastValidators.TotalVotingPower()
   370  
   371  	waitForAndValidateBlock(t, nVals, activeVals, blocksSubs, css, updateValidatorTx)
   372  	waitForAndValidateBlockWithTx(t, nVals, activeVals, blocksSubs, css, updateValidatorTx)
   373  	waitForAndValidateBlock(t, nVals, activeVals, blocksSubs, css)
   374  	waitForAndValidateBlock(t, nVals, activeVals, blocksSubs, css)
   375  
   376  	if css[0].GetRoundState().LastValidators.TotalVotingPower() == previousTotalVotingPower {
   377  		t.Fatalf(
   378  			"expected voting power to change (before: %d, after: %d)",
   379  			previousTotalVotingPower,
   380  			css[0].GetRoundState().LastValidators.TotalVotingPower())
   381  	}
   382  
   383  	updateValidatorTx = kvstore.MakeValSetChangeTx(val1PubKeyABCI, 26)
   384  	previousTotalVotingPower = css[0].GetRoundState().LastValidators.TotalVotingPower()
   385  
   386  	waitForAndValidateBlock(t, nVals, activeVals, blocksSubs, css, updateValidatorTx)
   387  	waitForAndValidateBlockWithTx(t, nVals, activeVals, blocksSubs, css, updateValidatorTx)
   388  	waitForAndValidateBlock(t, nVals, activeVals, blocksSubs, css)
   389  	waitForAndValidateBlock(t, nVals, activeVals, blocksSubs, css)
   390  
   391  	if css[0].GetRoundState().LastValidators.TotalVotingPower() == previousTotalVotingPower {
   392  		t.Fatalf(
   393  			"expected voting power to change (before: %d, after: %d)",
   394  			previousTotalVotingPower,
   395  			css[0].GetRoundState().LastValidators.TotalVotingPower())
   396  	}
   397  }
   398  
   399  func TestReactorValidatorSetChanges(t *testing.T) {
   400  	return
   401  	nPeers := 7
   402  	nVals := 4
   403  	css, _, _, cleanup := randConsensusNetWithPeers(
   404  		nVals,
   405  		nPeers,
   406  		"consensus_val_set_changes_test",
   407  		newMockTickerFunc(true),
   408  		newPersistentKVStoreWithPath)
   409  
   410  	defer cleanup()
   411  	logger := log.TestingLogger()
   412  
   413  	reactors, blocksSubs, eventBuses := startConsensusNet(t, css, nPeers)
   414  	defer stopConsensusNet(logger, reactors, eventBuses)
   415  
   416  	// map of active validators
   417  	activeVals := make(map[string]struct{})
   418  	for i := 0; i < nVals; i++ {
   419  		pubKey, err := css[i].privValidator.GetPubKey()
   420  		require.NoError(t, err)
   421  		activeVals[string(pubKey.Address())] = struct{}{}
   422  	}
   423  
   424  	// wait till everyone makes block 1
   425  	timeoutWaitGroup(t, nPeers, func(j int) {
   426  		<-blocksSubs[j].Out()
   427  	}, css)
   428  
   429  	//---------------------------------------------------------------------------
   430  	logger.Info("---------------------------- Testing adding one validator")
   431  
   432  	newValidatorPubKey1, err := css[nVals].privValidator.GetPubKey()
   433  	require.NoError(t, err)
   434  	valPubKey1ABCI := types.TM2PB.PubKey(newValidatorPubKey1)
   435  	newValidatorTx1 := kvstore.MakeValSetChangeTx(valPubKey1ABCI, testMinPower)
   436  
   437  	// wait till everyone makes block 2
   438  	// ensure the commit includes all validators
   439  	// send newValTx to change vals in block 3
   440  	waitForAndValidateBlock(t, nPeers, activeVals, blocksSubs, css, newValidatorTx1)
   441  
   442  	// wait till everyone makes block 3.
   443  	// it includes the commit for block 2, which is by the original validator set
   444  	waitForAndValidateBlockWithTx(t, nPeers, activeVals, blocksSubs, css, newValidatorTx1)
   445  
   446  	// wait till everyone makes block 4.
   447  	// it includes the commit for block 3, which is by the original validator set
   448  	waitForAndValidateBlock(t, nPeers, activeVals, blocksSubs, css)
   449  
   450  	// the commits for block 4 should be with the updated validator set
   451  	activeVals[string(newValidatorPubKey1.Address())] = struct{}{}
   452  
   453  	// wait till everyone makes block 5
   454  	// it includes the commit for block 4, which should have the updated validator set
   455  	waitForBlockWithUpdatedValsAndValidateIt(t, nPeers, activeVals, blocksSubs, css)
   456  
   457  	//---------------------------------------------------------------------------
   458  	logger.Info("---------------------------- Testing changing the voting power of one validator")
   459  
   460  	updateValidatorPubKey1, err := css[nVals].privValidator.GetPubKey()
   461  	require.NoError(t, err)
   462  	updatePubKey1ABCI := types.TM2PB.PubKey(updateValidatorPubKey1)
   463  	updateValidatorTx1 := kvstore.MakeValSetChangeTx(updatePubKey1ABCI, 25)
   464  	previousTotalVotingPower := css[nVals].GetRoundState().LastValidators.TotalVotingPower()
   465  
   466  	waitForAndValidateBlock(t, nPeers, activeVals, blocksSubs, css, updateValidatorTx1)
   467  	waitForAndValidateBlockWithTx(t, nPeers, activeVals, blocksSubs, css, updateValidatorTx1)
   468  	waitForAndValidateBlock(t, nPeers, activeVals, blocksSubs, css)
   469  	waitForBlockWithUpdatedValsAndValidateIt(t, nPeers, activeVals, blocksSubs, css)
   470  
   471  	if css[nVals].GetRoundState().LastValidators.TotalVotingPower() == previousTotalVotingPower {
   472  		t.Errorf(
   473  			"expected voting power to change (before: %d, after: %d)",
   474  			previousTotalVotingPower,
   475  			css[nVals].GetRoundState().LastValidators.TotalVotingPower())
   476  	}
   477  
   478  	//---------------------------------------------------------------------------
   479  	logger.Info("---------------------------- Testing adding two validators at once")
   480  
   481  	newValidatorPubKey2, err := css[nVals+1].privValidator.GetPubKey()
   482  	require.NoError(t, err)
   483  	newVal2ABCI := types.TM2PB.PubKey(newValidatorPubKey2)
   484  	newValidatorTx2 := kvstore.MakeValSetChangeTx(newVal2ABCI, testMinPower)
   485  
   486  	newValidatorPubKey3, err := css[nVals+2].privValidator.GetPubKey()
   487  	require.NoError(t, err)
   488  	newVal3ABCI := types.TM2PB.PubKey(newValidatorPubKey3)
   489  	newValidatorTx3 := kvstore.MakeValSetChangeTx(newVal3ABCI, testMinPower)
   490  
   491  	waitForAndValidateBlock(t, nPeers, activeVals, blocksSubs, css, newValidatorTx2, newValidatorTx3)
   492  	waitForAndValidateBlockWithTx(t, nPeers, activeVals, blocksSubs, css, newValidatorTx2, newValidatorTx3)
   493  	waitForAndValidateBlock(t, nPeers, activeVals, blocksSubs, css)
   494  	activeVals[string(newValidatorPubKey2.Address())] = struct{}{}
   495  	activeVals[string(newValidatorPubKey3.Address())] = struct{}{}
   496  	waitForBlockWithUpdatedValsAndValidateIt(t, nPeers, activeVals, blocksSubs, css)
   497  
   498  	//---------------------------------------------------------------------------
   499  	logger.Info("---------------------------- Testing removing two validators at once")
   500  
   501  	removeValidatorTx2 := kvstore.MakeValSetChangeTx(newVal2ABCI, 0)
   502  	removeValidatorTx3 := kvstore.MakeValSetChangeTx(newVal3ABCI, 0)
   503  
   504  	waitForAndValidateBlock(t, nPeers, activeVals, blocksSubs, css, removeValidatorTx2, removeValidatorTx3)
   505  	waitForAndValidateBlockWithTx(t, nPeers, activeVals, blocksSubs, css, removeValidatorTx2, removeValidatorTx3)
   506  	waitForAndValidateBlock(t, nPeers, activeVals, blocksSubs, css)
   507  	delete(activeVals, string(newValidatorPubKey2.Address()))
   508  	delete(activeVals, string(newValidatorPubKey3.Address()))
   509  	waitForBlockWithUpdatedValsAndValidateIt(t, nPeers, activeVals, blocksSubs, css)
   510  }
   511  
   512  // Check we can make blocks with skip_timeout_commit=false
   513  func TestReactorWithTimeoutCommit(t *testing.T) {
   514  	N := 4
   515  	css, cleanup := randConsensusNet(N, "consensus_reactor_with_timeout_commit_test", newMockTickerFunc(false), newCounter)
   516  	defer cleanup()
   517  	// override default SkipTimeoutCommit == true for tests
   518  	for i := 0; i < N; i++ {
   519  		css[i].config.SkipTimeoutCommit = false
   520  	}
   521  
   522  	reactors, blocksSubs, eventBuses := startConsensusNet(t, css, N-1)
   523  	defer stopConsensusNet(log.TestingLogger(), reactors, eventBuses)
   524  
   525  	// wait till everyone makes the first new block
   526  	timeoutWaitGroup(t, N-1, func(j int) {
   527  		<-blocksSubs[j].Out()
   528  	}, css)
   529  }
   530  
   531  func waitForAndValidateBlock(
   532  	t *testing.T,
   533  	n int,
   534  	activeVals map[string]struct{},
   535  	blocksSubs []types.Subscription,
   536  	css []*State,
   537  	txs ...[]byte,
   538  ) {
   539  	timeoutWaitGroup(t, n, func(j int) {
   540  		css[j].Logger.Debug("waitForAndValidateBlock")
   541  		msg := <-blocksSubs[j].Out()
   542  		newBlock := msg.Data().(types.EventDataNewBlock).Block
   543  		css[j].Logger.Debug("waitForAndValidateBlock: Got block", "height", newBlock.Height)
   544  		err := validateBlock(newBlock, activeVals)
   545  		assert.Nil(t, err)
   546  		for _, tx := range txs {
   547  			err := assertMempool(css[j].txNotifier).CheckTx(tx, nil, mempl.TxInfo{})
   548  			assert.Nil(t, err)
   549  		}
   550  	}, css)
   551  }
   552  
   553  func waitForAndValidateBlockWithTx(
   554  	t *testing.T,
   555  	n int,
   556  	activeVals map[string]struct{},
   557  	blocksSubs []types.Subscription,
   558  	css []*State,
   559  	txs ...[]byte,
   560  ) {
   561  	timeoutWaitGroup(t, n, func(j int) {
   562  		ntxs := 0
   563  	BLOCK_TX_LOOP:
   564  		for {
   565  			css[j].Logger.Debug("waitForAndValidateBlockWithTx", "ntxs", ntxs)
   566  			msg := <-blocksSubs[j].Out()
   567  			newBlock := msg.Data().(types.EventDataNewBlock).Block
   568  			css[j].Logger.Debug("waitForAndValidateBlockWithTx: Got block", "height", newBlock.Height)
   569  			err := validateBlock(newBlock, activeVals)
   570  			assert.Nil(t, err)
   571  
   572  			// check that txs match the txs we're waiting for.
   573  			// note they could be spread over multiple blocks,
   574  			// but they should be in order.
   575  			for _, tx := range newBlock.Data.Txs {
   576  				assert.EqualValues(t, txs[ntxs], tx)
   577  				ntxs++
   578  			}
   579  
   580  			if ntxs == len(txs) {
   581  				break BLOCK_TX_LOOP
   582  			}
   583  		}
   584  
   585  	}, css)
   586  }
   587  
   588  func waitForBlockWithUpdatedValsAndValidateIt(
   589  	t *testing.T,
   590  	n int,
   591  	updatedVals map[string]struct{},
   592  	blocksSubs []types.Subscription,
   593  	css []*State,
   594  ) {
   595  	timeoutWaitGroup(t, n, func(j int) {
   596  
   597  		var newBlock *types.Block
   598  	LOOP:
   599  		for {
   600  			css[j].Logger.Debug("waitForBlockWithUpdatedValsAndValidateIt")
   601  			msg := <-blocksSubs[j].Out()
   602  			newBlock = msg.Data().(types.EventDataNewBlock).Block
   603  			if newBlock.LastCommit.Size() == len(updatedVals) {
   604  				css[j].Logger.Debug("waitForBlockWithUpdatedValsAndValidateIt: Got block", "height", newBlock.Height)
   605  				break LOOP
   606  			} else {
   607  				css[j].Logger.Debug(
   608  					"waitForBlockWithUpdatedValsAndValidateIt: Got block with no new validators. Skipping",
   609  					"height",
   610  					newBlock.Height)
   611  			}
   612  		}
   613  
   614  		err := validateBlock(newBlock, updatedVals)
   615  		assert.Nil(t, err)
   616  	}, css)
   617  }
   618  
   619  // expects high synchrony!
   620  func validateBlock(block *types.Block, activeVals map[string]struct{}) error {
   621  	if block.LastCommit.Size() != len(activeVals) {
   622  		return fmt.Errorf(
   623  			"commit size doesn't match number of active validators. Got %d, expected %d",
   624  			block.LastCommit.Size(),
   625  			len(activeVals))
   626  	}
   627  
   628  	for _, commitSig := range block.LastCommit.Signatures {
   629  		if _, ok := activeVals[string(commitSig.ValidatorAddress)]; !ok {
   630  			return fmt.Errorf("found vote for inactive validator %X", commitSig.ValidatorAddress)
   631  		}
   632  	}
   633  	return nil
   634  }
   635  
   636  func timeoutWaitGroup(t *testing.T, n int, f func(int), css []*State) {
   637  	wg := new(sync.WaitGroup)
   638  	wg.Add(n)
   639  	for i := 0; i < n; i++ {
   640  		go func(j int) {
   641  			f(j)
   642  			wg.Done()
   643  		}(i)
   644  	}
   645  
   646  	done := make(chan struct{})
   647  	go func() {
   648  		wg.Wait()
   649  		close(done)
   650  	}()
   651  
   652  	// we're running many nodes in-process, possibly in in a virtual machine,
   653  	// and spewing debug messages - making a block could take a while,
   654  	timeout := time.Second * 300
   655  
   656  	select {
   657  	case <-done:
   658  	case <-time.After(timeout):
   659  		for i, cs := range css {
   660  			t.Log("#################")
   661  			t.Log("Validator", i)
   662  			t.Log(cs.GetRoundState())
   663  			t.Log("")
   664  		}
   665  		os.Stdout.Write([]byte("pprof.Lookup('goroutine'):\n"))
   666  		pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
   667  		capture()
   668  		panic("Timed out waiting for all validators to commit a block")
   669  	}
   670  }
   671  
   672  func capture() {
   673  	trace := make([]byte, 10240000)
   674  	count := runtime.Stack(trace, true)
   675  	fmt.Printf("Stack of %d bytes: %s\n", count, trace)
   676  }
   677  
   678  //-------------------------------------------------------------
   679  // Ensure basic validation of structs is functioning
   680  
   681  func TestNewRoundStepMessageValidateBasic(t *testing.T) {
   682  	testCases := []struct { // nolint: maligned
   683  		expectErr              bool
   684  		messageRound           int
   685  		messageLastCommitRound int
   686  		messageHeight          int64
   687  		testName               string
   688  		messageStep            cstypes.RoundStepType
   689  	}{
   690  		{false, 0, 0, 0, "Valid Message", 0x01},
   691  		{true, -1, 0, 0, "Invalid Message", 0x01},
   692  		{true, 0, 0, -1, "Invalid Message", 0x01},
   693  		{true, 0, 0, 1, "Invalid Message", 0x00},
   694  		{true, 0, 0, 1, "Invalid Message", 0x00},
   695  		{true, 0, -2, 2, "Invalid Message", 0x01},
   696  	}
   697  
   698  	for _, tc := range testCases {
   699  		tc := tc
   700  		t.Run(tc.testName, func(t *testing.T) {
   701  			message := NewRoundStepMessage{
   702  				Height:          tc.messageHeight,
   703  				Round:           tc.messageRound,
   704  				Step:            tc.messageStep,
   705  				LastCommitRound: tc.messageLastCommitRound,
   706  			}
   707  
   708  			assert.Equal(t, tc.expectErr, message.ValidateBasic() != nil, "Validate Basic had an unexpected result")
   709  		})
   710  	}
   711  }
   712  
   713  func TestNewValidBlockMessageValidateBasic(t *testing.T) {
   714  	testCases := []struct {
   715  		malleateFn func(*NewValidBlockMessage)
   716  		expErr     string
   717  	}{
   718  		{func(msg *NewValidBlockMessage) {}, ""},
   719  		{func(msg *NewValidBlockMessage) { msg.Height = -1 }, "negative Height"},
   720  		{func(msg *NewValidBlockMessage) { msg.Round = -1 }, "negative Round"},
   721  		{
   722  			func(msg *NewValidBlockMessage) { msg.BlockPartsHeader.Total = 2 },
   723  			"blockParts bit array size 1 not equal to BlockPartsHeader.Total 2",
   724  		},
   725  		{
   726  			func(msg *NewValidBlockMessage) { msg.BlockPartsHeader.Total = 0; msg.BlockParts = bits.NewBitArray(0) },
   727  			"empty blockParts",
   728  		},
   729  		{
   730  			func(msg *NewValidBlockMessage) { msg.BlockParts = bits.NewBitArray(types.MaxBlockPartsCount + 1) },
   731  			"blockParts bit array size 1602 not equal to BlockPartsHeader.Total 1",
   732  		},
   733  	}
   734  
   735  	for i, tc := range testCases {
   736  		tc := tc
   737  		t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
   738  			msg := &NewValidBlockMessage{
   739  				Height: 1,
   740  				Round:  0,
   741  				BlockPartsHeader: types.PartSetHeader{
   742  					Total: 1,
   743  				},
   744  				BlockParts: bits.NewBitArray(1),
   745  			}
   746  
   747  			tc.malleateFn(msg)
   748  			err := msg.ValidateBasic()
   749  			if tc.expErr != "" && assert.Error(t, err) {
   750  				assert.Contains(t, err.Error(), tc.expErr)
   751  			}
   752  		})
   753  	}
   754  }
   755  
   756  func TestProposalPOLMessageValidateBasic(t *testing.T) {
   757  	testCases := []struct {
   758  		malleateFn func(*ProposalPOLMessage)
   759  		expErr     string
   760  	}{
   761  		{func(msg *ProposalPOLMessage) {}, ""},
   762  		{func(msg *ProposalPOLMessage) { msg.Height = -1 }, "negative Height"},
   763  		{func(msg *ProposalPOLMessage) { msg.ProposalPOLRound = -1 }, "negative ProposalPOLRound"},
   764  		{func(msg *ProposalPOLMessage) { msg.ProposalPOL = bits.NewBitArray(0) }, "empty ProposalPOL bit array"},
   765  		{func(msg *ProposalPOLMessage) { msg.ProposalPOL = bits.NewBitArray(types.MaxVotesCount + 1) },
   766  			"ProposalPOL bit array is too big: 10001, max: 10000"},
   767  	}
   768  
   769  	for i, tc := range testCases {
   770  		tc := tc
   771  		t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
   772  			msg := &ProposalPOLMessage{
   773  				Height:           1,
   774  				ProposalPOLRound: 1,
   775  				ProposalPOL:      bits.NewBitArray(1),
   776  			}
   777  
   778  			tc.malleateFn(msg)
   779  			err := msg.ValidateBasic()
   780  			if tc.expErr != "" && assert.Error(t, err) {
   781  				assert.Contains(t, err.Error(), tc.expErr)
   782  			}
   783  		})
   784  	}
   785  }
   786  
   787  func TestBlockPartMessageValidateBasic(t *testing.T) {
   788  	testPart := new(types.Part)
   789  	testPart.Proof.LeafHash = tmhash.Sum([]byte("leaf"))
   790  	testCases := []struct {
   791  		testName      string
   792  		messageHeight int64
   793  		messageRound  int
   794  		messagePart   *types.Part
   795  		expectErr     bool
   796  	}{
   797  		{"Valid Message", 0, 0, testPart, false},
   798  		{"Invalid Message", -1, 0, testPart, true},
   799  		{"Invalid Message", 0, -1, testPart, true},
   800  	}
   801  
   802  	for _, tc := range testCases {
   803  		tc := tc
   804  		t.Run(tc.testName, func(t *testing.T) {
   805  			message := BlockPartMessage{
   806  				Height: tc.messageHeight,
   807  				Round:  tc.messageRound,
   808  				Part:   tc.messagePart,
   809  			}
   810  
   811  			assert.Equal(t, tc.expectErr, message.ValidateBasic() != nil, "Validate Basic had an unexpected result")
   812  		})
   813  	}
   814  
   815  	message := BlockPartMessage{Height: 0, Round: 0, Part: new(types.Part)}
   816  	message.Part.Index = -1
   817  
   818  	assert.Equal(t, true, message.ValidateBasic() != nil, "Validate Basic had an unexpected result")
   819  }
   820  
   821  func TestHasVoteMessageValidateBasic(t *testing.T) {
   822  	const (
   823  		validSignedMsgType   types.SignedMsgType = 0x01
   824  		invalidSignedMsgType types.SignedMsgType = 0x03
   825  	)
   826  
   827  	testCases := []struct { // nolint: maligned
   828  		expectErr     bool
   829  		messageRound  int
   830  		messageIndex  int
   831  		messageHeight int64
   832  		testName      string
   833  		messageType   types.SignedMsgType
   834  	}{
   835  		{false, 0, 0, 0, "Valid Message", validSignedMsgType},
   836  		{true, -1, 0, 0, "Invalid Message", validSignedMsgType},
   837  		{true, 0, -1, 0, "Invalid Message", validSignedMsgType},
   838  		{true, 0, 0, 0, "Invalid Message", invalidSignedMsgType},
   839  		{true, 0, 0, -1, "Invalid Message", validSignedMsgType},
   840  	}
   841  
   842  	for _, tc := range testCases {
   843  		tc := tc
   844  		t.Run(tc.testName, func(t *testing.T) {
   845  			message := HasVoteMessage{
   846  				Height: tc.messageHeight,
   847  				Round:  tc.messageRound,
   848  				Type:   tc.messageType,
   849  				Index:  tc.messageIndex,
   850  			}
   851  
   852  			assert.Equal(t, tc.expectErr, message.ValidateBasic() != nil, "Validate Basic had an unexpected result")
   853  		})
   854  	}
   855  }
   856  
   857  func TestVoteSetMaj23MessageValidateBasic(t *testing.T) {
   858  	const (
   859  		validSignedMsgType   types.SignedMsgType = 0x01
   860  		invalidSignedMsgType types.SignedMsgType = 0x03
   861  	)
   862  
   863  	validBlockID := types.BlockID{}
   864  	invalidBlockID := types.BlockID{
   865  		Hash: bytes.HexBytes{},
   866  		PartsHeader: types.PartSetHeader{
   867  			Total: -1,
   868  			Hash:  bytes.HexBytes{},
   869  		},
   870  	}
   871  
   872  	testCases := []struct { // nolint: maligned
   873  		expectErr      bool
   874  		messageRound   int
   875  		messageHeight  int64
   876  		testName       string
   877  		messageType    types.SignedMsgType
   878  		messageBlockID types.BlockID
   879  	}{
   880  		{false, 0, 0, "Valid Message", validSignedMsgType, validBlockID},
   881  		{true, -1, 0, "Invalid Message", validSignedMsgType, validBlockID},
   882  		{true, 0, -1, "Invalid Message", validSignedMsgType, validBlockID},
   883  		{true, 0, 0, "Invalid Message", invalidSignedMsgType, validBlockID},
   884  		{true, 0, 0, "Invalid Message", validSignedMsgType, invalidBlockID},
   885  	}
   886  
   887  	for _, tc := range testCases {
   888  		tc := tc
   889  		t.Run(tc.testName, func(t *testing.T) {
   890  			message := VoteSetMaj23Message{
   891  				Height:  tc.messageHeight,
   892  				Round:   tc.messageRound,
   893  				Type:    tc.messageType,
   894  				BlockID: tc.messageBlockID,
   895  			}
   896  
   897  			assert.Equal(t, tc.expectErr, message.ValidateBasic() != nil, "Validate Basic had an unexpected result")
   898  		})
   899  	}
   900  }
   901  
   902  func TestVoteSetBitsMessageValidateBasic(t *testing.T) {
   903  	testCases := []struct { // nolint: maligned
   904  		malleateFn func(*VoteSetBitsMessage)
   905  		expErr     string
   906  	}{
   907  		{func(msg *VoteSetBitsMessage) {}, ""},
   908  		{func(msg *VoteSetBitsMessage) { msg.Height = -1 }, "negative Height"},
   909  		{func(msg *VoteSetBitsMessage) { msg.Round = -1 }, "negative Round"},
   910  		{func(msg *VoteSetBitsMessage) { msg.Type = 0x03 }, "invalid Type"},
   911  		{func(msg *VoteSetBitsMessage) {
   912  			msg.BlockID = types.BlockID{
   913  				Hash: bytes.HexBytes{},
   914  				PartsHeader: types.PartSetHeader{
   915  					Total: -1,
   916  					Hash:  bytes.HexBytes{},
   917  				},
   918  			}
   919  		}, "wrong BlockID: wrong PartsHeader: negative Total"},
   920  		{func(msg *VoteSetBitsMessage) { msg.Votes = bits.NewBitArray(types.MaxVotesCount + 1) },
   921  			"votes bit array is too big: 10001, max: 10000"},
   922  	}
   923  
   924  	for i, tc := range testCases {
   925  		tc := tc
   926  		t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
   927  			msg := &VoteSetBitsMessage{
   928  				Height:  1,
   929  				Round:   0,
   930  				Type:    0x01,
   931  				Votes:   bits.NewBitArray(1),
   932  				BlockID: types.BlockID{},
   933  			}
   934  
   935  			tc.malleateFn(msg)
   936  			err := msg.ValidateBasic()
   937  			if tc.expErr != "" && assert.Error(t, err) {
   938  				assert.Contains(t, err.Error(), tc.expErr)
   939  			}
   940  		})
   941  	}
   942  }