github.com/reapchain/go-reapchain@v0.2.15-0.20210609012950-9735c110c705/consensus/podc/core/commit.go (about)

     1  // Copyright 2017 AMIS Technologies
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package core
    18  
    19  import (
    20  	"reflect"
    21  
    22  	"github.com/ethereum/go-ethereum/consensus/podc"
    23  )
    24  
    25  func (c *core) sendCommit() {
    26  	logger := c.logger.New("state", c.state)
    27  
    28  	sub := c.current.Subject()
    29  	encodedSubject, err := Encode(sub)
    30  	if err != nil {
    31  		logger.Error("Failed to encode", "subject", sub)
    32  		return
    33  	}
    34  	c.broadcast(&message{
    35  		Code: msgCommit,
    36  		Msg:  encodedSubject,
    37  	})
    38  }
    39  
    40  func (c *core) handleCommit(msg *message, src podc.Validator) error {
    41  	// Decode commit message
    42  	var commit *podc.Subject
    43  	err := msg.Decode(&commit)
    44  	if err != nil {
    45  		return errFailedDecodeCommit
    46  	}
    47  
    48  	if err := c.checkMessage(msgCommit, commit.View); err != nil {
    49  		return err
    50  	}
    51  
    52  	if err := c.verifyCommit(commit, src); err != nil {
    53  		return err
    54  	}
    55  
    56  	c.acceptCommit(msg, src)
    57  
    58  	// Commit the proposal once we have enough commit messages and we are not in StateCommitted.
    59  	//
    60  	// If we already have a proposal, we may have chance to speed up the consensus process
    61  	// by committing the proposal without prepare messages.
    62  	if c.current.Commits.Size() > 2*c.valSet.F() && c.state.Cmp(StateCommitted) < 0 {
    63  		c.commit()
    64  	}
    65  
    66  	return nil
    67  }
    68  
    69  // verifyCommit verifies if the received commit message is equivalent to our subject
    70  func (c *core) verifyCommit(commit *podc.Subject, src podc.Validator) error {
    71  	logger := c.logger.New("from", src, "state", c.state)
    72  
    73  	sub := c.current.Subject()
    74  	if !reflect.DeepEqual(commit, sub) {
    75  		logger.Warn("Inconsistent subjects between commit and proposal(verifyCommit)", "expected", sub, "got", commit)
    76  		return errInconsistentSubject
    77  	}
    78  
    79  	return nil
    80  }
    81  
    82  func (c *core) acceptCommit(msg *message, src podc.Validator) error {
    83  	logger := c.logger.New("from", src, "state", c.state)
    84  
    85  	// Add the commit message to current round state
    86  	if err := c.current.Commits.Add(msg); err != nil {
    87  		logger.Error("Failed to record commit message", "msg", msg, "err", err)
    88  		return err
    89  	}
    90  
    91  	return nil
    92  }