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  }