github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/consensus/istanbul/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  	"bytes"
    21  	"errors"
    22  	"io"
    23  	"math/big"
    24  	"sync"
    25  
    26  	"github.com/ethereum/go-ethereum/consensus/istanbul/validator"
    27  	"github.com/ethereum/go-ethereum/log"
    28  
    29  	"github.com/ethereum/go-ethereum/common"
    30  	"github.com/ethereum/go-ethereum/consensus/istanbul"
    31  	"github.com/ethereum/go-ethereum/rlp"
    32  )
    33  
    34  var (
    35  	// errFailedCreatePreparedCertificate is returned when there aren't enough PREPARE messages to create a PREPARED certificate.
    36  	errFailedCreatePreparedCertificate = errors.New("failed to create PREPARED certficate")
    37  )
    38  
    39  type RoundState interface {
    40  	// mutation functions
    41  	StartNewRound(nextRound *big.Int, validatorSet istanbul.ValidatorSet, nextProposer istanbul.Validator) error
    42  	StartNewSequence(nextSequence *big.Int, validatorSet istanbul.ValidatorSet, nextProposer istanbul.Validator, parentCommits MessageSet) error
    43  	TransitionToPreprepared(preprepare *istanbul.Preprepare) error
    44  	TransitionToWaitingForNewRound(r *big.Int, nextProposer istanbul.Validator) error
    45  	TransitionToCommitted() error
    46  	TransitionToPrepared(quorumSize int) error
    47  	AddCommit(msg *istanbul.Message) error
    48  	AddPrepare(msg *istanbul.Message) error
    49  	AddParentCommit(msg *istanbul.Message) error
    50  	SetPendingRequest(pendingRequest *istanbul.Request) error
    51  	SetProposalVerificationStatus(proposalHash common.Hash, verificationStatus error)
    52  
    53  	// view functions
    54  	DesiredRound() *big.Int
    55  	State() State
    56  	GetPrepareOrCommitSize() int
    57  	GetValidatorByAddress(address common.Address) istanbul.Validator
    58  	ValidatorSet() istanbul.ValidatorSet
    59  	Proposer() istanbul.Validator
    60  	IsProposer(address common.Address) bool
    61  	Subject() *istanbul.Subject
    62  	Preprepare() *istanbul.Preprepare
    63  	Proposal() istanbul.Proposal
    64  	Round() *big.Int
    65  	Commits() MessageSet
    66  	Prepares() MessageSet
    67  	ParentCommits() MessageSet
    68  	PendingRequest() *istanbul.Request
    69  	Sequence() *big.Int
    70  	View() *istanbul.View
    71  	PreparedCertificate() istanbul.PreparedCertificate
    72  	GetProposalVerificationStatus(proposalHash common.Hash) (verificationStatus error, isCached bool)
    73  	Summary() *RoundStateSummary
    74  }
    75  
    76  // RoundState stores the consensus state
    77  type roundStateImpl struct {
    78  	state        State
    79  	round        *big.Int
    80  	desiredRound *big.Int
    81  	sequence     *big.Int
    82  
    83  	// data for current round
    84  	preprepare *istanbul.Preprepare
    85  	prepares   MessageSet
    86  	commits    MessageSet
    87  	proposer   istanbul.Validator
    88  
    89  	// data saves across rounds, same sequence
    90  	validatorSet        istanbul.ValidatorSet
    91  	parentCommits       MessageSet
    92  	pendingRequest      *istanbul.Request
    93  	preparedCertificate istanbul.PreparedCertificate
    94  
    95  	// Verification status for proposals seen in this view
    96  	// Note that this field will not get RLP enoded and persisted, since it contains an error type,
    97  	// which doesn't have a native RLP encoding.  Also, this is a cache, so it's not necessary for it
    98  	// to be persisted.
    99  	proposalVerificationStatus map[common.Hash]error
   100  
   101  	mu     *sync.RWMutex
   102  	logger log.Logger
   103  }
   104  
   105  type RoundStateSummary struct {
   106  	State              string       `json:"state"`
   107  	Sequence           *big.Int     `json:"sequence"`
   108  	Round              *big.Int     `json:"round"`
   109  	DesiredRound       *big.Int     `json:"desiredRound"`
   110  	PendingRequestHash *common.Hash `json:"pendingRequestHash"`
   111  
   112  	ValidatorSet []common.Address `json:"validatorSet"`
   113  	Proposer     common.Address   `json:"proposer"`
   114  
   115  	Prepares      []common.Address `json:"prepares"`
   116  	Commits       []common.Address `json:"commits"`
   117  	ParentCommits []common.Address `json:"parentCommits"`
   118  
   119  	Preprepare          *istanbul.PreprepareSummary          `json:"preprepare"`
   120  	PreparedCertificate *istanbul.PreparedCertificateSummary `json:"preparedCertificate"`
   121  }
   122  
   123  func newRoundState(view *istanbul.View, validatorSet istanbul.ValidatorSet, proposer istanbul.Validator) RoundState {
   124  	return &roundStateImpl{
   125  		state:        StateAcceptRequest,
   126  		round:        view.Round,
   127  		desiredRound: view.Round,
   128  		sequence:     view.Sequence,
   129  
   130  		// data for current round
   131  		// preprepare: nil,
   132  		prepares: newMessageSet(validatorSet),
   133  		commits:  newMessageSet(validatorSet),
   134  		proposer: proposer,
   135  
   136  		// data saves across rounds, same sequence
   137  		validatorSet:        validatorSet,
   138  		parentCommits:       newMessageSet(validatorSet),
   139  		pendingRequest:      nil,
   140  		preparedCertificate: istanbul.EmptyPreparedCertificate(),
   141  
   142  		mu:     new(sync.RWMutex),
   143  		logger: log.New(),
   144  	}
   145  }
   146  
   147  func (rs *roundStateImpl) Commits() MessageSet       { return rs.commits }
   148  func (rs *roundStateImpl) Prepares() MessageSet      { return rs.prepares }
   149  func (rs *roundStateImpl) ParentCommits() MessageSet { return rs.parentCommits }
   150  
   151  func (rs *roundStateImpl) State() State {
   152  	rs.mu.RLock()
   153  	defer rs.mu.RUnlock()
   154  	return rs.state
   155  }
   156  
   157  func (rs *roundStateImpl) View() *istanbul.View {
   158  	rs.mu.RLock()
   159  	defer rs.mu.RUnlock()
   160  
   161  	return &istanbul.View{
   162  		Sequence: new(big.Int).Set(rs.sequence),
   163  		Round:    new(big.Int).Set(rs.round),
   164  	}
   165  }
   166  
   167  func (rs *roundStateImpl) GetPrepareOrCommitSize() int {
   168  	rs.mu.RLock()
   169  	defer rs.mu.RUnlock()
   170  
   171  	result := rs.prepares.Size() + rs.commits.Size()
   172  
   173  	// find duplicate one
   174  	for _, m := range rs.prepares.Values() {
   175  		if rs.commits.Get(m.Address) != nil {
   176  			result--
   177  		}
   178  	}
   179  	return result
   180  }
   181  
   182  func (rs *roundStateImpl) Subject() *istanbul.Subject {
   183  	rs.mu.RLock()
   184  	defer rs.mu.RUnlock()
   185  
   186  	if rs.preprepare == nil {
   187  		return nil
   188  	}
   189  
   190  	return &istanbul.Subject{
   191  		View: &istanbul.View{
   192  			Round:    new(big.Int).Set(rs.round),
   193  			Sequence: new(big.Int).Set(rs.sequence),
   194  		},
   195  		Digest: rs.preprepare.Proposal.Hash(),
   196  	}
   197  }
   198  
   199  func (rs *roundStateImpl) IsProposer(address common.Address) bool {
   200  	rs.mu.RLock()
   201  	defer rs.mu.RUnlock()
   202  
   203  	return rs.proposer.Address() == address
   204  }
   205  
   206  func (rs *roundStateImpl) Proposer() istanbul.Validator {
   207  	rs.mu.RLock()
   208  	defer rs.mu.RUnlock()
   209  
   210  	return rs.proposer
   211  }
   212  
   213  func (rs *roundStateImpl) ValidatorSet() istanbul.ValidatorSet {
   214  	rs.mu.RLock()
   215  	defer rs.mu.RUnlock()
   216  
   217  	return rs.validatorSet
   218  }
   219  
   220  func (rs *roundStateImpl) GetValidatorByAddress(address common.Address) istanbul.Validator {
   221  	rs.mu.RLock()
   222  	defer rs.mu.RUnlock()
   223  
   224  	_, validator := rs.validatorSet.GetByAddress(address)
   225  	return validator
   226  }
   227  
   228  func (rs *roundStateImpl) Preprepare() *istanbul.Preprepare {
   229  	rs.mu.RLock()
   230  	defer rs.mu.RUnlock()
   231  
   232  	return rs.preprepare
   233  }
   234  
   235  func (rs *roundStateImpl) Proposal() istanbul.Proposal {
   236  	rs.mu.RLock()
   237  	defer rs.mu.RUnlock()
   238  
   239  	if rs.preprepare != nil {
   240  		return rs.preprepare.Proposal
   241  	}
   242  
   243  	return nil
   244  }
   245  
   246  func (rs *roundStateImpl) Round() *big.Int {
   247  	rs.mu.RLock()
   248  	defer rs.mu.RUnlock()
   249  
   250  	return rs.round
   251  }
   252  
   253  func (rs *roundStateImpl) changeRound(nextRound *big.Int, validatorSet istanbul.ValidatorSet, nextProposer istanbul.Validator) {
   254  	rs.state = StateAcceptRequest
   255  	rs.round = nextRound
   256  	rs.desiredRound = nextRound
   257  
   258  	// TODO MC use old valset
   259  	rs.prepares = newMessageSet(validatorSet)
   260  	rs.commits = newMessageSet(validatorSet)
   261  	rs.proposer = nextProposer
   262  
   263  	// ??
   264  	rs.preprepare = nil
   265  }
   266  
   267  func (rs *roundStateImpl) StartNewRound(nextRound *big.Int, validatorSet istanbul.ValidatorSet, nextProposer istanbul.Validator) error {
   268  	rs.mu.Lock()
   269  	defer rs.mu.Unlock()
   270  	logger := rs.newLogger()
   271  	rs.changeRound(nextRound, validatorSet, nextProposer)
   272  	logger.Debug("Starting new round", "next_round", nextRound, "next_proposer", nextProposer.Address().Hex())
   273  	return nil
   274  }
   275  
   276  func (rs *roundStateImpl) StartNewSequence(nextSequence *big.Int, validatorSet istanbul.ValidatorSet, nextProposer istanbul.Validator, parentCommits MessageSet) error {
   277  	rs.mu.Lock()
   278  	defer rs.mu.Unlock()
   279  	logger := rs.newLogger()
   280  
   281  	rs.validatorSet = validatorSet
   282  
   283  	rs.changeRound(big.NewInt(0), validatorSet, nextProposer)
   284  
   285  	rs.sequence = nextSequence
   286  	rs.preparedCertificate = istanbul.EmptyPreparedCertificate()
   287  	rs.pendingRequest = nil
   288  	rs.parentCommits = parentCommits
   289  	rs.proposalVerificationStatus = nil
   290  
   291  	logger.Debug("Starting new sequence", "next_sequence", nextSequence, "next_proposer", nextProposer.Address().Hex())
   292  	return nil
   293  }
   294  
   295  func (rs *roundStateImpl) TransitionToCommitted() error {
   296  	rs.mu.Lock()
   297  	defer rs.mu.Unlock()
   298  
   299  	rs.state = StateCommitted
   300  	return nil
   301  }
   302  
   303  func (rs *roundStateImpl) TransitionToPreprepared(preprepare *istanbul.Preprepare) error {
   304  	rs.mu.Lock()
   305  	defer rs.mu.Unlock()
   306  
   307  	rs.preprepare = preprepare
   308  	rs.state = StatePreprepared
   309  	return nil
   310  }
   311  
   312  func (rs *roundStateImpl) TransitionToWaitingForNewRound(r *big.Int, nextProposer istanbul.Validator) error {
   313  	rs.mu.Lock()
   314  	defer rs.mu.Unlock()
   315  
   316  	rs.desiredRound = new(big.Int).Set(r)
   317  	rs.proposer = nextProposer
   318  	rs.state = StateWaitingForNewRound
   319  	return nil
   320  }
   321  
   322  // TransitionToPrepared will create a PreparedCertificate and change state to Prepared
   323  func (rs *roundStateImpl) TransitionToPrepared(quorumSize int) error {
   324  	rs.mu.Lock()
   325  	defer rs.mu.Unlock()
   326  
   327  	messages := make([]istanbul.Message, quorumSize)
   328  	i := 0
   329  	for _, message := range rs.prepares.Values() {
   330  		if i == quorumSize {
   331  			break
   332  		}
   333  		messages[i] = *message
   334  		i++
   335  	}
   336  	for _, message := range rs.commits.Values() {
   337  		if i == quorumSize {
   338  			break
   339  		}
   340  		if rs.prepares.Get(message.Address) == nil {
   341  			messages[i] = *message
   342  			i++
   343  		}
   344  	}
   345  	if i != quorumSize {
   346  		return errFailedCreatePreparedCertificate
   347  	}
   348  	rs.preparedCertificate = istanbul.PreparedCertificate{
   349  		Proposal:                rs.preprepare.Proposal,
   350  		PrepareOrCommitMessages: messages,
   351  	}
   352  
   353  	rs.state = StatePrepared
   354  	return nil
   355  }
   356  
   357  func (rs *roundStateImpl) AddCommit(msg *istanbul.Message) error {
   358  	rs.mu.Lock()
   359  	defer rs.mu.Unlock()
   360  	return rs.commits.Add(msg)
   361  }
   362  
   363  func (rs *roundStateImpl) AddPrepare(msg *istanbul.Message) error {
   364  	rs.mu.Lock()
   365  	defer rs.mu.Unlock()
   366  	return rs.prepares.Add(msg)
   367  }
   368  
   369  func (rs *roundStateImpl) AddParentCommit(msg *istanbul.Message) error {
   370  	rs.mu.Lock()
   371  	defer rs.mu.Unlock()
   372  	return rs.parentCommits.Add(msg)
   373  }
   374  
   375  func (rs *roundStateImpl) DesiredRound() *big.Int {
   376  	rs.mu.RLock()
   377  	defer rs.mu.RUnlock()
   378  
   379  	return rs.desiredRound
   380  }
   381  
   382  func (rs *roundStateImpl) SetPendingRequest(pendingRequest *istanbul.Request) error {
   383  	rs.mu.Lock()
   384  	defer rs.mu.Unlock()
   385  
   386  	rs.pendingRequest = pendingRequest
   387  	return nil
   388  }
   389  
   390  func (rs *roundStateImpl) PendingRequest() *istanbul.Request {
   391  	rs.mu.RLock()
   392  	defer rs.mu.RUnlock()
   393  	return rs.pendingRequest
   394  }
   395  
   396  func (rs *roundStateImpl) Sequence() *big.Int {
   397  	rs.mu.RLock()
   398  	defer rs.mu.RUnlock()
   399  
   400  	return rs.sequence
   401  }
   402  
   403  func (rs *roundStateImpl) PreparedCertificate() istanbul.PreparedCertificate {
   404  	rs.mu.RLock()
   405  	defer rs.mu.RUnlock()
   406  	return rs.preparedCertificate
   407  }
   408  
   409  func (rs *roundStateImpl) SetProposalVerificationStatus(proposalHash common.Hash, verificationStatus error) {
   410  	rs.mu.Lock()
   411  	defer rs.mu.Unlock()
   412  
   413  	if rs.proposalVerificationStatus == nil {
   414  		rs.proposalVerificationStatus = make(map[common.Hash]error)
   415  	}
   416  
   417  	rs.proposalVerificationStatus[proposalHash] = verificationStatus
   418  }
   419  
   420  func (rs *roundStateImpl) GetProposalVerificationStatus(proposalHash common.Hash) (verificationStatus error, isCached bool) {
   421  	rs.mu.RLock()
   422  	defer rs.mu.RUnlock()
   423  
   424  	verificationStatus, isCached = nil, false
   425  
   426  	if rs.proposalVerificationStatus != nil {
   427  		verificationStatus, isCached = rs.proposalVerificationStatus[proposalHash]
   428  	}
   429  
   430  	return
   431  }
   432  
   433  func (rs *roundStateImpl) Summary() *RoundStateSummary {
   434  	rs.mu.RLock()
   435  	defer rs.mu.RUnlock()
   436  
   437  	summary := &RoundStateSummary{
   438  		State:        rs.state.String(),
   439  		Sequence:     rs.sequence,
   440  		Round:        rs.round,
   441  		DesiredRound: rs.desiredRound,
   442  
   443  		Proposer:     rs.proposer.Address(),
   444  		ValidatorSet: istanbul.MapValidatorsToAddresses(rs.validatorSet.List()),
   445  
   446  		Prepares:      rs.prepares.Addresses(),
   447  		Commits:       rs.commits.Addresses(),
   448  		ParentCommits: rs.parentCommits.Addresses(),
   449  	}
   450  
   451  	if rs.pendingRequest != nil {
   452  		hash := rs.pendingRequest.Proposal.Hash()
   453  		summary.PendingRequestHash = &hash
   454  	}
   455  
   456  	if rs.preprepare != nil {
   457  		summary.Preprepare = rs.preprepare.Summary()
   458  	}
   459  
   460  	if !rs.preparedCertificate.IsEmpty() {
   461  		summary.PreparedCertificate = rs.preparedCertificate.Summary()
   462  	}
   463  
   464  	return summary
   465  }
   466  
   467  func (rs *roundStateImpl) newLogger(ctx ...interface{}) log.Logger {
   468  	logger := rs.logger.New(ctx...)
   469  	return logger.New("cur_seq", rs.sequence, "cur_round", rs.round, "state", rs.state)
   470  }
   471  
   472  type roundStateRLP struct {
   473  	State               State
   474  	Round               *big.Int
   475  	DesiredRound        *big.Int
   476  	Sequence            *big.Int
   477  	PreparedCertificate *istanbul.PreparedCertificate
   478  
   479  	// custom serialized fields
   480  	SerializedValSet         []byte
   481  	SerializedProposer       []byte
   482  	SerializedParentCommits  []byte
   483  	SerializedPrepares       []byte
   484  	SerializedCommits        []byte
   485  	SerializedPreprepare     []byte
   486  	SerializedPendingRequest []byte
   487  }
   488  
   489  // EncodeRLP should write the RLP encoding of its receiver to w.
   490  // If the implementation is a pointer method, it may also be
   491  // called for nil pointers.
   492  //
   493  // Implementations should generate valid RLP. The data written is
   494  // not verified at the moment, but a future version might. It is
   495  // recommended to write only a single value but writing multiple
   496  // values or no value at all is also permitted.
   497  func (rs *roundStateImpl) EncodeRLP(w io.Writer) error {
   498  	rs.mu.RLock()
   499  	defer rs.mu.RUnlock()
   500  
   501  	serializedValSet, err := rs.validatorSet.Serialize()
   502  	if err != nil {
   503  		return err
   504  	}
   505  	serializedProposer, err := rs.proposer.Serialize()
   506  	if err != nil {
   507  		return err
   508  	}
   509  
   510  	serializedParentCommits, err := rs.parentCommits.Serialize()
   511  	if err != nil {
   512  		return err
   513  	}
   514  	serializedPrepares, err := rs.prepares.Serialize()
   515  	if err != nil {
   516  		return err
   517  	}
   518  	serializedCommits, err := rs.commits.Serialize()
   519  	if err != nil {
   520  		return err
   521  	}
   522  
   523  	// handle nullable field. Serialized them to rlp.EmptyList or the rlp version of them
   524  	var serializedPendingRequest []byte
   525  	if rs.pendingRequest == nil {
   526  		serializedPendingRequest = rlp.EmptyList
   527  	} else {
   528  		serializedPendingRequest, err = rlp.EncodeToBytes(rs.pendingRequest)
   529  		if err != nil {
   530  			return err
   531  		}
   532  	}
   533  
   534  	var serializedPreprepare []byte
   535  	if rs.preprepare == nil {
   536  		serializedPreprepare = rlp.EmptyList
   537  	} else {
   538  		serializedPreprepare, err = rlp.EncodeToBytes(rs.preprepare)
   539  		if err != nil {
   540  			return err
   541  		}
   542  	}
   543  
   544  	entry := roundStateRLP{
   545  		State:               rs.state,
   546  		Round:               rs.round,
   547  		DesiredRound:        rs.desiredRound,
   548  		Sequence:            rs.sequence,
   549  		PreparedCertificate: &rs.preparedCertificate,
   550  
   551  		SerializedValSet:         serializedValSet,
   552  		SerializedProposer:       serializedProposer,
   553  		SerializedParentCommits:  serializedParentCommits,
   554  		SerializedPrepares:       serializedPrepares,
   555  		SerializedCommits:        serializedCommits,
   556  		SerializedPendingRequest: serializedPendingRequest,
   557  		SerializedPreprepare:     serializedPreprepare,
   558  	}
   559  	return rlp.Encode(w, entry)
   560  }
   561  
   562  // The DecodeRLP method should read one value from the given
   563  // Stream. It is not forbidden to read less or more, but it might
   564  // be confusing.
   565  func (rs *roundStateImpl) DecodeRLP(stream *rlp.Stream) error {
   566  	var data roundStateRLP
   567  	err := stream.Decode(&data)
   568  	if err != nil {
   569  		return err
   570  	}
   571  
   572  	rs.logger = log.New()
   573  	rs.mu = new(sync.RWMutex)
   574  	rs.state = data.State
   575  	rs.round = data.Round
   576  	rs.desiredRound = data.DesiredRound
   577  	rs.sequence = data.Sequence
   578  	rs.preparedCertificate = *data.PreparedCertificate
   579  
   580  	rs.prepares, err = deserializeMessageSet(data.SerializedPrepares)
   581  	if err != nil {
   582  		return err
   583  	}
   584  	rs.parentCommits, err = deserializeMessageSet(data.SerializedParentCommits)
   585  	if err != nil {
   586  		return err
   587  	}
   588  	rs.commits, err = deserializeMessageSet(data.SerializedCommits)
   589  	if err != nil {
   590  		return err
   591  	}
   592  	rs.validatorSet, err = validator.DeserializeValidatorSet(data.SerializedValSet)
   593  	if err != nil {
   594  		return err
   595  	}
   596  	rs.proposer, err = validator.DeserializeValidator(data.SerializedProposer)
   597  	if err != nil {
   598  		return err
   599  	}
   600  
   601  	if !bytes.Equal(data.SerializedPendingRequest, rlp.EmptyList) {
   602  		var value istanbul.Request
   603  		err := rlp.DecodeBytes(data.SerializedPendingRequest, &value)
   604  		if err != nil {
   605  			return err
   606  		}
   607  		rs.pendingRequest = &value
   608  
   609  	}
   610  
   611  	if !bytes.Equal(data.SerializedPreprepare, rlp.EmptyList) {
   612  		var value istanbul.Preprepare
   613  		err := rlp.DecodeBytes(data.SerializedPreprepare, &value)
   614  		if err != nil {
   615  			return err
   616  		}
   617  		rs.preprepare = &value
   618  	}
   619  
   620  	return nil
   621  }