github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/consensus/pbft/core/prepare.go (about)

     1  // Copyright 2020 The go-simplechain Authors
     2  // This file is part of the go-simplechain library.
     3  //
     4  // The go-simplechain 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-simplechain 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-simplechain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package core
    18  
    19  import (
    20  	"reflect"
    21  	"time"
    22  
    23  	"github.com/bigzoro/my_simplechain/consensus/pbft"
    24  )
    25  
    26  func (c *core) sendPrepare() {
    27  
    28  	logger := c.logger.New("state", c.state)
    29  
    30  	sub := c.current.Subject()
    31  
    32  	//logger.Error("send prepare", "subject", sub)
    33  
    34  	encodedSubject, err := Encode(sub)
    35  	if err != nil {
    36  		logger.Error("Failed to encode", "subject", sub)
    37  		return
    38  	}
    39  
    40  	prepareMsg := &message{
    41  		Code: msgPrepare,
    42  		Msg:  encodedSubject,
    43  	}
    44  
    45  	//c.broadcast(prepareMsg, true)
    46  
    47  	c.broadcast(prepareMsg, false)
    48  	c.acceptPrepare(prepareMsg, sub.View)
    49  	c.checkAndPrepare(sub)
    50  }
    51  
    52  func (c *core) handlePrepare(msg *message, src pbft.Validator) error {
    53  	c.prepareTimestamp = time.Now()
    54  
    55  	// Decode PsREPARE message
    56  	var prepare *pbft.Subject
    57  	err := msg.Decode(&prepare)
    58  	if err != nil {
    59  		return errFailedDecodePrepare
    60  	}
    61  
    62  	if err := c.checkMessage(msgPrepare, prepare.View); err != nil {
    63  		return err
    64  	}
    65  	// If it is locked, it can only process on the locked block.
    66  	// Passing verifyPrepare and checkMessage implies it is processing on the locked block since it was verified in the Preprepared state.
    67  	if err := c.verifyPrepare(prepare, src); err != nil {
    68  		return err
    69  	}
    70  	c.acceptPrepare(msg, prepare.View)
    71  	c.checkAndPrepare(prepare)
    72  
    73  	return nil
    74  }
    75  
    76  // verifyPrepare verifies if the received PREPARE message is equivalent to our subject
    77  func (c *core) verifyPrepare(prepare *pbft.Subject, src pbft.Validator) error {
    78  	logger := c.logger.New("from", src, "state", c.state)
    79  
    80  	sub := c.current.Subject()
    81  	if !reflect.DeepEqual(prepare, sub) {
    82  		logger.Warn("Inconsistent subjects between PREPARE and proposal", "expected", sub, "got", prepare)
    83  		return errInconsistentSubject
    84  	}
    85  
    86  	return nil
    87  }
    88  
    89  func (c *core) acceptPrepare(msg *message, view *pbft.View) error {
    90  	logger := c.logger.New("from", msg.Address, "state", c.state)
    91  	logger.Trace("accept prepare msg", "view", view, "lockHash", c.current.lockedHash)
    92  	//logger.Error("[report] accept prepare msg", "view", view, "lockHash", c.current.lockedHash)
    93  
    94  	// Add the PREPARE message to current round state
    95  	if err := c.current.Prepares.Add(msg); err != nil {
    96  		logger.Error("Failed to add PREPARE message to round state", "msg", msg, "err", err)
    97  		return err
    98  	}
    99  
   100  	return nil
   101  }
   102  
   103  func (c *core) checkAndPrepare(prepare *pbft.Subject) {
   104  	// Change to Prepared state if we've received enough PREPARE messages or it is locked
   105  	// and we are in earlier state before Prepared state.
   106  	if ((c.current.IsHashLocked() && prepare.Digest == c.current.GetLockedHash()) ||
   107  		c.current.GetPrepareOrCommitSize() >= c.Confirmations()) && c.state.Cmp(StatePrepared) < 0 {
   108  		c.current.LockHash()
   109  		c.setState(StatePrepared)
   110  		c.sendCommit()
   111  	}
   112  }