github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/consensus/dbft/core/commit.go (about)

     1  package core
     2  
     3  import (
     4  	"reflect"
     5  
     6  	"github.com/quickchainproject/quickchain/common"
     7  	bft "github.com/quickchainproject/quickchain/consensus/dbft"
     8  )
     9  
    10  func (c *core) sendCommit() {
    11  	sub := c.current.Subject()
    12  	c.broadcastCommit(sub)
    13  }
    14  
    15  func (c *core) sendCommitForOldBlock(view *bft.View, digest common.Hash) {
    16  	sub := &bft.Subject{
    17  		View:   view,
    18  		Digest: digest,
    19  	}
    20  	c.broadcastCommit(sub)
    21  }
    22  
    23  func (c *core) broadcastCommit(sub *bft.Subject) {
    24  	logger := c.logger.New("state", c.state)
    25  
    26  	encodedSubject, err := Encode(sub)
    27  	if err != nil {
    28  		logger.Error("Failed to encode", "subject", sub)
    29  		return
    30  	}
    31  	c.broadcast(&message{
    32  		Code: msgCommit,
    33  		Msg:  encodedSubject,
    34  	})
    35  }
    36  
    37  func (c *core) handleCommit(msg *message, src bft.Validator) error {
    38  	// Decode COMMIT message
    39  	var commit *bft.Subject
    40  	err := msg.Decode(&commit)
    41  	if err != nil {
    42  		return errFailedDecodeCommit
    43  	}
    44  
    45  	if err := c.checkMessage(msgCommit, commit.View); err != nil {
    46  		return err
    47  	}
    48  
    49  	if err := c.verifyCommit(commit, src); err != nil {
    50  		return err
    51  	}
    52  
    53  	c.acceptCommit(msg, src)
    54  
    55  	// Commit the proposal once we have enough COMMIT messages and we are not in the Committed state.
    56  	//
    57  	// If we already have a proposal, we may have chance to speed up the consensus process
    58  	// by committing the proposal without PREPARE messages.
    59  	if c.current.Commits.Size() > 2*c.valSet.F() && c.state.Cmp(StateCommitted) < 0 {
    60  		// Still need to call LockHash here since state can skip Prepared state and jump directly to the Committed state.
    61  		c.current.LockHash()
    62  		c.commit()
    63  	}
    64  
    65  	return nil
    66  }
    67  
    68  // verifyCommit verifies if the received COMMIT message is equivalent to our subject
    69  func (c *core) verifyCommit(commit *bft.Subject, src bft.Validator) error {
    70  	logger := c.logger.New("from", src, "state", c.state)
    71  
    72  	sub := c.current.Subject()
    73  	if !reflect.DeepEqual(commit, sub) {
    74  		logger.Warn("Inconsistent subjects between commit and proposal", "expected", sub, "got", commit)
    75  		return errInconsistentSubject
    76  	}
    77  
    78  	return nil
    79  }
    80  
    81  func (c *core) acceptCommit(msg *message, src bft.Validator) error {
    82  	logger := c.logger.New("from", src, "state", c.state)
    83  
    84  	// Add the COMMIT message to current round state
    85  	if err := c.current.Commits.Add(msg); err != nil {
    86  		logger.Error("Failed to record commit message", "msg", msg, "err", err)
    87  		return err
    88  	}
    89  
    90  	return nil
    91  }