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

     1  // Copyright 2017 The go-ethereum Authors
     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  	"io"
    21  	"math/big"
    22  	"runtime/debug"
    23  	"sync"
    24  
    25  	"github.com/bigzoro/my_simplechain/common"
    26  	"github.com/bigzoro/my_simplechain/consensus/pbft"
    27  	"github.com/bigzoro/my_simplechain/rlp"
    28  )
    29  
    30  // newRoundState creates a new roundState instance with the given view and validatorSet
    31  // lockedHash and preprepare are for round change when lock exists,
    32  // we need to keep a reference of preprepare in order to propose locked proposal when there is a lock and itself is the proposer
    33  func newRoundState(view *pbft.View, validatorSet pbft.ValidatorSet, lockedHash common.Hash, preprepare *pbft.Preprepare,
    34  	prepare pbft.Conclusion, pendingRequest *pbft.Request, hasBadProposal func(hash common.Hash) bool) *roundState {
    35  	return &roundState{
    36  		round:          view.Round,
    37  		sequence:       view.Sequence,
    38  		Preprepare:     preprepare,
    39  		Prepare:        prepare,
    40  		Prepares:       newMessageSet(validatorSet),
    41  		Commits:        newMessageSet(validatorSet),
    42  		lockedHash:     lockedHash,
    43  		mu:             new(sync.RWMutex),
    44  		pendingRequest: pendingRequest,
    45  		hasBadProposal: hasBadProposal,
    46  	}
    47  }
    48  
    49  // roundState stores the consensus state
    50  type roundState struct {
    51  	round          *big.Int
    52  	sequence       *big.Int
    53  	LightPrepare   *pbft.LightPreprepare
    54  	Preprepare     *pbft.Preprepare
    55  	Prepare        pbft.Conclusion // executed proposal
    56  	Prepares       *messageSet
    57  	Commits        *messageSet
    58  	lockedHash     common.Hash
    59  	pendingRequest *pbft.Request
    60  
    61  	mu             *sync.RWMutex
    62  	hasBadProposal func(hash common.Hash) bool
    63  }
    64  
    65  func (s *roundState) GetPrepareOrCommitSize() int {
    66  	s.mu.RLock()
    67  	defer s.mu.RUnlock()
    68  
    69  	result := s.Prepares.Size() + s.Commits.Size()
    70  
    71  	// find duplicate one
    72  	for _, m := range s.Prepares.Values() {
    73  		if s.Commits.Get(m.Address) != nil {
    74  			result--
    75  		}
    76  	}
    77  	return result
    78  }
    79  
    80  func (s *roundState) Subject() *pbft.Subject {
    81  	s.mu.RLock()
    82  	defer s.mu.RUnlock()
    83  
    84  	if s.Preprepare == nil || s.Prepare == nil {
    85  		return nil
    86  	}
    87  
    88  	return &pbft.Subject{
    89  		View: &pbft.View{
    90  			Round:    new(big.Int).Set(s.round),
    91  			Sequence: new(big.Int).Set(s.sequence),
    92  		},
    93  		Pending: s.Preprepare.Proposal.PendingHash(), // pending hash of proposal
    94  		Digest:  s.Prepare.Hash(),                    // hash of conclusion
    95  	}
    96  }
    97  
    98  func (s *roundState) SetLightPrepare(preprepare *pbft.LightPreprepare) {
    99  	s.mu.Lock()
   100  	defer s.mu.Unlock()
   101  
   102  	s.LightPrepare = preprepare
   103  }
   104  
   105  func (s *roundState) SetPreprepare(preprepare *pbft.Preprepare) {
   106  	s.mu.Lock()
   107  	defer s.mu.Unlock()
   108  
   109  	s.Preprepare = preprepare
   110  }
   111  
   112  func (s *roundState) SetPrepare(prepare pbft.Conclusion) {
   113  	s.mu.Lock()
   114  	defer s.mu.Unlock()
   115  
   116  	s.Prepare = prepare
   117  }
   118  
   119  func (s *roundState) Proposal() pbft.Proposal {
   120  	s.mu.RLock()
   121  	defer s.mu.RUnlock()
   122  
   123  	if s.Preprepare != nil {
   124  		return s.Preprepare.Proposal
   125  	}
   126  	return nil
   127  }
   128  
   129  // return light block proposal,
   130  // return nil if the proposal is not exist or not a light proposal
   131  func (s *roundState) LightProposal() pbft.LightProposal {
   132  	s.mu.RLock()
   133  	defer s.mu.RUnlock()
   134  
   135  	if s.LightPrepare != nil {
   136  		return s.LightPrepare.Proposal.(pbft.LightProposal)
   137  	}
   138  	return nil
   139  }
   140  
   141  func (s *roundState) Conclusion() pbft.Conclusion {
   142  	s.mu.RLock()
   143  	defer s.mu.RUnlock()
   144  
   145  	if s.Prepare != nil {
   146  		return s.Prepare
   147  	}
   148  
   149  	return nil
   150  }
   151  
   152  func (s *roundState) SetRound(r *big.Int) {
   153  	s.mu.Lock()
   154  	defer s.mu.Unlock()
   155  
   156  	s.round = new(big.Int).Set(r)
   157  }
   158  
   159  func (s *roundState) Round() *big.Int {
   160  	s.mu.RLock()
   161  	defer s.mu.RUnlock()
   162  
   163  	return s.round
   164  }
   165  
   166  func (s *roundState) SetSequence(seq *big.Int) {
   167  	s.mu.Lock()
   168  	defer s.mu.Unlock()
   169  
   170  	s.sequence = seq
   171  }
   172  
   173  func (s *roundState) Sequence() *big.Int {
   174  	s.mu.RLock()
   175  	defer s.mu.RUnlock()
   176  
   177  	return s.sequence
   178  }
   179  
   180  func (s *roundState) LockHash() {
   181  	s.mu.Lock()
   182  	defer s.mu.Unlock()
   183  
   184  	if s.Preprepare != nil {
   185  		s.lockedHash = s.Preprepare.Proposal.PendingHash()
   186  	}
   187  }
   188  
   189  func (s *roundState) UnlockHash() {
   190  	s.mu.Lock()
   191  	defer s.mu.Unlock()
   192  
   193  	s.lockedHash = common.Hash{}
   194  }
   195  
   196  func (s *roundState) IsHashLocked() bool {
   197  	s.mu.RLock()
   198  	defer s.mu.RUnlock()
   199  
   200  	if (common.Hash{}) == s.lockedHash {
   201  		return false
   202  	}
   203  	return !s.hasBadProposal(s.GetLockedHash())
   204  }
   205  
   206  func (s *roundState) GetLockedHash() common.Hash {
   207  	s.mu.RLock()
   208  	defer s.mu.RUnlock()
   209  
   210  	return s.lockedHash
   211  }
   212  
   213  // The DecodeRLP method should read one value from the given
   214  // Stream. It is not forbidden to read less or more, but it might
   215  // be confusing.
   216  func (s *roundState) DecodeRLP(stream *rlp.Stream) error {
   217  	debug.PrintStack()
   218  	var ss struct {
   219  		Round          *big.Int
   220  		Sequence       *big.Int
   221  		Preprepare     *pbft.Preprepare
   222  		Prepares       *messageSet
   223  		Commits        *messageSet
   224  		lockedHash     common.Hash
   225  		pendingRequest *pbft.Request
   226  	}
   227  
   228  	if err := stream.Decode(&ss); err != nil {
   229  		return err
   230  	}
   231  	s.round = ss.Round
   232  	s.sequence = ss.Sequence
   233  	s.Preprepare = ss.Preprepare
   234  	s.Prepares = ss.Prepares
   235  	s.Commits = ss.Commits
   236  	s.lockedHash = ss.lockedHash
   237  	s.pendingRequest = ss.pendingRequest
   238  	s.mu = new(sync.RWMutex)
   239  
   240  	return nil
   241  }
   242  
   243  // EncodeRLP should write the RLP encoding of its receiver to w.
   244  // If the implementation is a pointer method, it may also be
   245  // called for nil pointers.
   246  //
   247  // Implementations should generate valid RLP. The data written is
   248  // not verified at the moment, but a future version might. It is
   249  // recommended to write only a single value but writing multiple
   250  // values or no value at all is also permitted.
   251  func (s *roundState) EncodeRLP(w io.Writer) error {
   252  	s.mu.RLock()
   253  	defer s.mu.RUnlock()
   254  
   255  	return rlp.Encode(w, []interface{}{
   256  		s.round,
   257  		s.sequence,
   258  		s.Preprepare,
   259  		s.Prepares,
   260  		s.Commits,
   261  		s.lockedHash,
   262  		s.pendingRequest,
   263  	})
   264  }