github.com/annchain/OG@v0.0.9/poc/tendermint/client_byzantine_test.go (about) 1 package tendermint 2 3 import ( 4 "github.com/annchain/OG/ffchan" 5 "github.com/sirupsen/logrus" 6 "time" 7 ) 8 9 type ByzantineFeatures struct { 10 SilenceProposal bool 11 SilencePreVote bool 12 SilencePreCommit bool 13 BadProposal bool 14 BadPreVote bool 15 BadPreCommit bool 16 } 17 18 // ByzantinePartner implements a Tendermint client according to "The latest gossip on BFT consensus" 19 type ByzantinePartner struct { 20 *DefaultPartner 21 // consider updating resetStatus() if you want to add things here 22 ByzantineFeatures ByzantineFeatures 23 } 24 25 func NewByzantinePartner(nbParticipants int, id int, blockTime time.Duration, byzantineFeatures ByzantineFeatures) *ByzantinePartner { 26 p := &ByzantinePartner{ 27 DefaultPartner: NewPartner(nbParticipants, id, blockTime), 28 ByzantineFeatures: byzantineFeatures, 29 } 30 return p 31 } 32 33 func (p *ByzantinePartner) EventLoop() { 34 go p.send() 35 go p.receive() 36 } 37 38 // send is just for outgoing messages. It should not change any state of local tendermint 39 func (p *ByzantinePartner) send() { 40 timer := time.NewTimer(time.Second * 7) 41 for { 42 timer.Reset(time.Second * 7) 43 select { 44 case <-p.quit: 45 break 46 case <-timer.C: 47 logrus.WithField("IM", p.Id).Warn("Blocked reading outgoing") 48 p.dumpAll("blocked reading outgoing(byzantine)") 49 case msg := <-p.OutgoingMessageChannel: 50 msg, tosend := p.doBadThings(msg) 51 if !tosend { 52 // don't send it 53 logrus.WithFields(logrus.Fields{ 54 "IM---BAD": p.Id, 55 "from": p.Id, 56 "msg": msg.String(), 57 }).Info("Eat message") 58 continue 59 } 60 for _, peer := range p.Peers { 61 logrus.WithFields(logrus.Fields{ 62 "IM---BAD": p.Id, 63 "from": p.Id, 64 "to": peer.GetId(), 65 "msg": msg.String(), 66 }).Tracef("PeerOutgoing message") 67 <-ffchan.NewTimeoutSenderShort(peer.GetIncomingMessageChannel(), msg, "").C 68 } 69 } 70 } 71 } 72 func (p *ByzantinePartner) doBadThings(msg Message) (updatedMessage Message, toSend bool) { 73 updatedMessage = msg 74 toSend = true 75 switch msg.Type { 76 case MessageTypeProposal: 77 if p.ByzantineFeatures.SilenceProposal { 78 toSend = false 79 } else if p.ByzantineFeatures.BadProposal { 80 v := updatedMessage.Payload.(MessageProposal) 81 v.HeightRound.Round++ 82 updatedMessage.Payload = v 83 } 84 85 case MessageTypePreVote: 86 if p.ByzantineFeatures.SilencePreVote { 87 toSend = false 88 } else if p.ByzantineFeatures.BadPreVote { 89 v := updatedMessage.Payload.(MessageCommonVote) 90 v.HeightRound.Round++ 91 updatedMessage.Payload = v 92 } 93 case MessageTypePreCommit: 94 if p.ByzantineFeatures.SilencePreCommit { 95 toSend = false 96 } else if p.ByzantineFeatures.BadPreCommit { 97 v := updatedMessage.Payload.(MessageCommonVote) 98 v.HeightRound.Round++ 99 updatedMessage.Payload = v 100 } 101 102 } 103 return 104 }