github.com/Finschia/ostracon@v1.1.5/consensus/invalid_test.go (about)

     1  package consensus
     2  
     3  import (
     4  	"testing"
     5  
     6  	tmcons "github.com/tendermint/tendermint/proto/tendermint/consensus"
     7  	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
     8  
     9  	"github.com/Finschia/ostracon/libs/bytes"
    10  	"github.com/Finschia/ostracon/libs/log"
    11  	tmrand "github.com/Finschia/ostracon/libs/rand"
    12  	"github.com/Finschia/ostracon/p2p"
    13  	"github.com/Finschia/ostracon/types"
    14  )
    15  
    16  //----------------------------------------------
    17  // byzantine failures
    18  
    19  // one byz val sends a precommit for a random block at each height
    20  // Ensure a testnet makes blocks
    21  func TestReactorInvalidPrecommit(t *testing.T) {
    22  	N := 4
    23  	css, cleanup := randConsensusNet(N, "consensus_reactor_test", newMockTickerFunc(true), newCounter)
    24  	defer cleanup()
    25  
    26  	for i := 0; i < 4; i++ {
    27  		ticker := NewTimeoutTicker()
    28  		ticker.SetLogger(css[i].Logger)
    29  		css[i].SetTimeoutTicker(ticker)
    30  
    31  	}
    32  
    33  	reactors, blocksSubs, eventBuses := startConsensusNet(t, css, N)
    34  
    35  	// this val sends a random precommit at each height
    36  	byzValIdx := 0
    37  	byzVal := css[byzValIdx]
    38  	byzR := reactors[byzValIdx]
    39  
    40  	// update the doPrevote function to just send a valid precommit for a random block
    41  	// and otherwise disable the priv validator
    42  	byzVal.mtx.Lock()
    43  	pv := byzVal.privValidator
    44  	byzVal.doPrevote = func(height int64, round int32) {
    45  		invalidDoPrevoteFunc(t, height, round, byzVal, byzR.Switch, pv)
    46  	}
    47  	byzVal.mtx.Unlock()
    48  	defer stopConsensusNet(log.TestingLogger(), reactors, eventBuses)
    49  
    50  	// wait for a bunch of blocks
    51  	// TODO: make this tighter by ensuring the halt happens by block 2
    52  	for i := 0; i < 1; i++ { // XXX `i < 10` is too much count, so we changed to `i < 1`
    53  		timeoutWaitGroup(t, N, func(j int) {
    54  			<-blocksSubs[j].Out()
    55  		}, css)
    56  	}
    57  }
    58  
    59  func invalidDoPrevoteFunc(t *testing.T, height int64, round int32, cs *State, sw *p2p.Switch, pv types.PrivValidator) {
    60  	// routine to:
    61  	// - precommit for a random block
    62  	// - send precommit to all peers
    63  	// - disable privValidator (so we don't do normal precommits)
    64  	go func() {
    65  		cs.mtx.Lock()
    66  		cs.privValidator = pv
    67  		pubKey, err := cs.privValidator.GetPubKey()
    68  		if err != nil {
    69  			panic(err)
    70  		}
    71  		addr := pubKey.Address()
    72  		valIndex, _ := cs.Validators.GetByAddress(addr)
    73  
    74  		// precommit a random block
    75  		blockHash := bytes.HexBytes(tmrand.Bytes(32))
    76  		precommit := &types.Vote{
    77  			ValidatorAddress: addr,
    78  			ValidatorIndex:   valIndex,
    79  			Height:           cs.Height,
    80  			Round:            cs.Round,
    81  			Timestamp:        cs.voteTime(),
    82  			Type:             tmproto.PrecommitType,
    83  			BlockID: types.BlockID{
    84  				Hash:          blockHash,
    85  				PartSetHeader: types.PartSetHeader{Total: 1, Hash: tmrand.Bytes(32)}},
    86  		}
    87  		p := precommit.ToProto()
    88  		err = cs.privValidator.SignVote(cs.state.ChainID, p)
    89  		if err != nil {
    90  			t.Error(err)
    91  		}
    92  		precommit.Signature = p.Signature
    93  		cs.privValidator = nil // disable priv val so we don't do normal votes
    94  		cs.mtx.Unlock()
    95  
    96  		peers := sw.Peers().List()
    97  		for _, peer := range peers {
    98  			cs.Logger.Info("Sending bad vote", "block", blockHash, "peer", peer)
    99  			p2p.SendEnvelopeShim(peer, p2p.Envelope{ //nolint: staticcheck
   100  				Message:   &tmcons.Vote{Vote: precommit.ToProto()},
   101  				ChannelID: VoteChannel,
   102  			}, cs.Logger)
   103  		}
   104  	}()
   105  }