github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/consensus/dbft/core/handler.go (about) 1 package core 2 3 import ( 4 "github.com/quickchainproject/quickchain/common" 5 bft "github.com/quickchainproject/quickchain/consensus/dbft" 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("err handleMsg", "msg", msg) 126 logger.Error("Failed to decode message from payload", "err", err) 127 return err 128 } 129 130 // Only accept message if the address is valid 131 _, src := c.valSet.GetByAddress(msg.Address) 132 if src == nil { 133 logger.Error("Invalid address in message", "msg", msg) 134 return bft.ErrUnauthorizedAddress 135 } 136 137 return c.handleCheckedMsg(msg, src) 138 } 139 140 func (c *core) handleCheckedMsg(msg *message, src bft.Validator) error { 141 logger := c.logger.New("address", c.address, "from", src) 142 143 // Store the message if it's a future message 144 testBacklog := func(err error) error { 145 if err == errFutureMessage { 146 c.storeBacklog(msg, src) 147 } 148 149 return err 150 } 151 152 switch msg.Code { 153 case msgPreprepare: 154 return testBacklog(c.handlePreprepare(msg, src)) 155 case msgPrepare: 156 return testBacklog(c.handlePrepare(msg, src)) 157 case msgCommit: 158 return testBacklog(c.handleCommit(msg, src)) 159 case msgRoundChange: 160 return testBacklog(c.handleRoundChange(msg, src)) 161 default: 162 logger.Error("Invalid message", "msg", msg) 163 } 164 165 return errInvalidMessage 166 } 167 168 func (c *core) handleTimeoutMsg() { 169 // If we're not waiting for round change yet, we can try to catch up 170 // the max round with F+1 round change message. We only need to catch up 171 // if the max round is larger than current round. 172 if !c.waitingForRoundChange { 173 maxRound := c.roundChangeSet.MaxRound(c.valSet.F() + 1) 174 if maxRound != nil && maxRound.Cmp(c.current.Round()) > 0 { 175 c.sendRoundChange(maxRound) 176 return 177 } 178 } 179 180 lastProposal, _ := c.backend.LastProposal() 181 if lastProposal != nil && lastProposal.Number().Cmp(c.current.Sequence()) >= 0 { 182 c.logger.Trace("round change timeout, catch up latest sequence", "number", lastProposal.Number().Uint64()) 183 c.startNewRound(common.Big0) 184 } else { 185 c.sendNextRoundChange() 186 } 187 }