github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/consensus/bft/core/handler.go (about) 1 package core 2 3 import ( 4 "github.com/quickchainproject/quickchain/common" 5 "github.com/quickchainproject/quickchain/consensus/bft" 6 ) 7 8 // Start implements core.Engine.Start 9 func (c *core) Start() error { 10 // Start a new round from last sequence + 1 11 c.startNewRound(common.Big0) 12 13 // Tests will handle events itself, so we have to make subscribeEvents() 14 // be able to call in test. 15 c.subscribeEvents() 16 go c.handleEvents() 17 18 return nil 19 } 20 21 // Stop implements core.Engine.Stop 22 func (c *core) Stop() error { 23 c.stopTimer() 24 c.unsubscribeEvents() 25 26 // Make sure the handler goroutine exits 27 c.handlerWg.Wait() 28 return nil 29 } 30 31 // ---------------------------------------------------------------------------- 32 33 // Subscribe both internal and external events 34 func (c *core) subscribeEvents() { 35 c.events = c.backend.EventMux().Subscribe( 36 // external events 37 bft.RequestEvent{}, 38 bft.MessageEvent{}, 39 // internal events 40 backlogEvent{}, 41 ) 42 c.timeoutSub = c.backend.EventMux().Subscribe( 43 timeoutEvent{}, 44 ) 45 c.finalCommittedSub = c.backend.EventMux().Subscribe( 46 bft.FinalCommittedEvent{}, 47 ) 48 } 49 50 // Unsubscribe all events 51 func (c *core) unsubscribeEvents() { 52 c.events.Unsubscribe() 53 c.timeoutSub.Unsubscribe() 54 c.finalCommittedSub.Unsubscribe() 55 } 56 57 func (c *core) handleEvents() { 58 // Clear state 59 defer func() { 60 c.current = nil 61 c.handlerWg.Done() 62 }() 63 64 c.handlerWg.Add(1) 65 66 for { 67 select { 68 case event, ok := <-c.events.Chan(): 69 if !ok { 70 return 71 } 72 // A real event arrived, process interesting content 73 switch ev := event.Data.(type) { 74 case bft.RequestEvent: 75 r := &bft.Request{ 76 Proposal: ev.Proposal, 77 } 78 err := c.handleRequest(r) 79 if err == errFutureMessage { 80 c.storeRequestMsg(r) 81 } 82 case bft.MessageEvent: 83 if err := c.handleMsg(ev.Payload); err == nil { 84 c.backend.Gossip(c.valSet, ev.Payload) 85 } 86 case backlogEvent: 87 // No need to check signature for internal messages 88 if err := c.handleCheckedMsg(ev.msg, ev.src); err == nil { 89 p, err := ev.msg.Payload() 90 if err != nil { 91 c.logger.Warn("Get message payload failed", "err", err) 92 continue 93 } 94 c.backend.Gossip(c.valSet, p) 95 } 96 } 97 case _, ok := <-c.timeoutSub.Chan(): 98 if !ok { 99 return 100 } 101 c.handleTimeoutMsg() 102 case event, ok := <-c.finalCommittedSub.Chan(): 103 if !ok { 104 return 105 } 106 switch event.Data.(type) { 107 case bft.FinalCommittedEvent: 108 c.handleFinalCommitted() 109 } 110 } 111 } 112 } 113 114 // sendEvent sends events to mux 115 func (c *core) sendEvent(ev interface{}) { 116 c.backend.EventMux().Post(ev) 117 } 118 119 func (c *core) handleMsg(payload []byte) error { 120 logger := c.logger.New() 121 122 // Decode message and check its signature 123 msg := new(message) 124 if err := msg.FromPayload(payload, c.validateFn); err != nil { 125 logger.Error("Failed to decode message from payload", "err", err) 126 return err 127 } 128 129 // Only accept message if the address is valid 130 _, src := c.valSet.GetByAddress(msg.Address) 131 if src == nil { 132 logger.Error("Invalid address in message", "msg", msg) 133 return bft.ErrUnauthorizedAddress 134 } 135 136 return c.handleCheckedMsg(msg, src) 137 } 138 139 func (c *core) handleCheckedMsg(msg *message, src bft.Validator) error { 140 logger := c.logger.New("address", c.address, "from", src) 141 142 // Store the message if it's a future message 143 testBacklog := func(err error) error { 144 if err == errFutureMessage { 145 c.storeBacklog(msg, src) 146 } 147 148 return err 149 } 150 151 switch msg.Code { 152 case msgPreprepare: 153 return testBacklog(c.handlePreprepare(msg, src)) 154 case msgPrepare: 155 return testBacklog(c.handlePrepare(msg, src)) 156 case msgCommit: 157 return testBacklog(c.handleCommit(msg, src)) 158 case msgRoundChange: 159 return testBacklog(c.handleRoundChange(msg, src)) 160 default: 161 logger.Error("Invalid message", "msg", msg) 162 } 163 164 return errInvalidMessage 165 } 166 167 func (c *core) handleTimeoutMsg() { 168 // If we're not waiting for round change yet, we can try to catch up 169 // the max round with F+1 round change message. We only need to catch up 170 // if the max round is larger than current round. 171 if !c.waitingForRoundChange { 172 maxRound := c.roundChangeSet.MaxRound(c.valSet.F() + 1) 173 if maxRound != nil && maxRound.Cmp(c.current.Round()) > 0 { 174 c.sendRoundChange(maxRound) 175 return 176 } 177 } 178 179 lastProposal, _ := c.backend.LastProposal() 180 if lastProposal != nil && lastProposal.Number().Cmp(c.current.Sequence()) >= 0 { 181 c.logger.Trace("round change timeout, catch up latest sequence", "number", lastProposal.Number().Uint64()) 182 c.startNewRound(common.Big0) 183 } else { 184 c.sendNextRoundChange() 185 } 186 }