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