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  }