github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/consensus/istanbul/core/core.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  	"fmt"
    22  	"math"
    23  	"math/big"
    24  	"sync"
    25  	"time"
    26  
    27  	"github.com/ethereum/go-ethereum/common"
    28  	"github.com/ethereum/go-ethereum/common/prque"
    29  	"github.com/ethereum/go-ethereum/consensus"
    30  	"github.com/ethereum/go-ethereum/consensus/istanbul"
    31  	"github.com/ethereum/go-ethereum/consensus/istanbul/validator"
    32  	"github.com/ethereum/go-ethereum/core/types"
    33  	blscrypto "github.com/ethereum/go-ethereum/crypto/bls"
    34  	"github.com/ethereum/go-ethereum/event"
    35  	"github.com/ethereum/go-ethereum/log"
    36  	"github.com/ethereum/go-ethereum/metrics"
    37  	"github.com/syndtr/goleveldb/leveldb"
    38  )
    39  
    40  type core struct {
    41  	config         *istanbul.Config
    42  	address        common.Address
    43  	logger         log.Logger
    44  	selectProposer istanbul.ProposerSelector
    45  
    46  	backend           istanbul.Backend
    47  	events            *event.TypeMuxSubscription
    48  	finalCommittedSub *event.TypeMuxSubscription
    49  	timeoutSub        *event.TypeMuxSubscription
    50  
    51  	futurePreprepareTimer         *time.Timer
    52  	resendRoundChangeMessageTimer *time.Timer
    53  	roundChangeTimer              *time.Timer
    54  
    55  	validateFn func([]byte, []byte) (common.Address, error)
    56  
    57  	backlog MsgBacklog
    58  
    59  	rsdb      RoundStateDB
    60  	current   RoundState
    61  	handlerWg *sync.WaitGroup
    62  
    63  	roundChangeSet *roundChangeSet
    64  
    65  	pendingRequests   *prque.Prque
    66  	pendingRequestsMu *sync.Mutex
    67  
    68  	consensusTimestamp time.Time
    69  	// the meter to record the round change rate
    70  	roundMeter metrics.Meter
    71  	// the meter to record the sequence update rate
    72  	sequenceMeter metrics.Meter
    73  	// the timer to record consensus duration (from accepting a preprepare to final committed stage)
    74  	consensusTimer metrics.Timer
    75  }
    76  
    77  // New creates an Istanbul consensus core
    78  func New(backend istanbul.Backend, config *istanbul.Config) Engine {
    79  	rsdb, err := newRoundStateDB(config.RoundStateDBPath, nil)
    80  	if err != nil {
    81  		log.Crit("Failed to open RoundStateDB", "err", err)
    82  	}
    83  
    84  	c := &core{
    85  		config:             config,
    86  		address:            backend.Address(),
    87  		logger:             log.New(),
    88  		selectProposer:     validator.GetProposerSelector(config.ProposerPolicy),
    89  		handlerWg:          new(sync.WaitGroup),
    90  		backend:            backend,
    91  		pendingRequests:    prque.New(nil),
    92  		pendingRequestsMu:  new(sync.Mutex),
    93  		consensusTimestamp: time.Time{},
    94  		rsdb:               rsdb,
    95  		roundMeter:         metrics.NewRegisteredMeter("consensus/istanbul/core/round", nil),
    96  		sequenceMeter:      metrics.NewRegisteredMeter("consensus/istanbul/core/sequence", nil),
    97  		consensusTimer:     metrics.NewRegisteredTimer("consensus/istanbul/core/consensus", nil),
    98  	}
    99  	msgBacklog := newMsgBacklog(
   100  		func(msg *istanbul.Message) {
   101  			c.sendEvent(backlogEvent{
   102  				msg: msg,
   103  			})
   104  		}, c.checkMessage)
   105  	c.backlog = msgBacklog
   106  	c.validateFn = c.checkValidatorSignature
   107  	c.logger = istanbul.NewIstLogger(
   108  		func() *big.Int {
   109  			if c != nil && c.current != nil {
   110  				return c.current.Round()
   111  			}
   112  			return common.Big0
   113  		},
   114  	)
   115  	return c
   116  }
   117  
   118  // ----------------------------------------------------------------------------
   119  
   120  func (c *core) SetAddress(address common.Address) {
   121  	c.address = address
   122  	c.logger = log.New("address", address)
   123  }
   124  
   125  func (c *core) CurrentView() *istanbul.View {
   126  	if c.current == nil {
   127  		return nil
   128  	}
   129  	return c.current.View()
   130  }
   131  
   132  func (c *core) CurrentRoundState() RoundState { return c.current }
   133  
   134  func (c *core) ParentCommits() MessageSet {
   135  	if c.current == nil {
   136  		return nil
   137  	}
   138  	return c.current.ParentCommits()
   139  }
   140  
   141  func (c *core) ForceRoundChange() {
   142  	// timeout current DesiredView
   143  	view := &istanbul.View{Sequence: c.current.Sequence(), Round: c.current.DesiredRound()}
   144  	c.sendEvent(timeoutAndMoveToNextRoundEvent{view})
   145  }
   146  
   147  // PrepareCommittedSeal returns a committed seal for the given hash and round number.
   148  func PrepareCommittedSeal(hash common.Hash, round *big.Int) []byte {
   149  	var buf bytes.Buffer
   150  	buf.Write(hash.Bytes())
   151  	buf.Write(round.Bytes())
   152  	buf.Write([]byte{byte(istanbul.MsgCommit)})
   153  	return buf.Bytes()
   154  }
   155  
   156  // GetAggregatedSeal aggregates all the given seals for a given message set to a bls aggregated
   157  // signature and bitmap
   158  func GetAggregatedSeal(seals MessageSet, round *big.Int) (types.IstanbulAggregatedSeal, error) {
   159  	bitmap := big.NewInt(0)
   160  	committedSeals := make([][]byte, seals.Size())
   161  	for i, v := range seals.Values() {
   162  		committedSeals[i] = make([]byte, types.IstanbulExtraBlsSignature)
   163  
   164  		var commit *istanbul.CommittedSubject
   165  		err := v.Decode(&commit)
   166  		if err != nil {
   167  			return types.IstanbulAggregatedSeal{}, err
   168  		}
   169  		copy(committedSeals[i][:], commit.CommittedSeal[:])
   170  
   171  		j, err := seals.GetAddressIndex(v.Address)
   172  		if err != nil {
   173  			return types.IstanbulAggregatedSeal{}, err
   174  		}
   175  		bitmap.SetBit(bitmap, int(j), 1)
   176  	}
   177  
   178  	asig, err := blscrypto.AggregateSignatures(committedSeals)
   179  	if err != nil {
   180  		return types.IstanbulAggregatedSeal{}, err
   181  	}
   182  	return types.IstanbulAggregatedSeal{Bitmap: bitmap, Signature: asig, Round: round}, nil
   183  }
   184  
   185  // UnionOfSeals combines a BLS aggregated signature with an array of signatures. Accounts for
   186  // double aggregating the same signature by only adding aggregating if the
   187  // validator was not found in the previous bitmap.
   188  // This function assumes that the provided seals' validator set is the same one
   189  // which produced the provided bitmap
   190  func UnionOfSeals(aggregatedSignature types.IstanbulAggregatedSeal, seals MessageSet) (types.IstanbulAggregatedSeal, error) {
   191  	// TODO(asa): Check for round equality...
   192  	// Check who already has signed the message
   193  	newBitmap := new(big.Int).Set(aggregatedSignature.Bitmap)
   194  	committedSeals := [][]byte{}
   195  	committedSeals = append(committedSeals, aggregatedSignature.Signature)
   196  	for _, v := range seals.Values() {
   197  		valIndex, err := seals.GetAddressIndex(v.Address)
   198  		if err != nil {
   199  			return types.IstanbulAggregatedSeal{}, err
   200  		}
   201  
   202  		var commit *istanbul.CommittedSubject
   203  		err = v.Decode(&commit)
   204  		if err != nil {
   205  			return types.IstanbulAggregatedSeal{}, err
   206  		}
   207  
   208  		// if the bit was not set, this means we should add this signature to
   209  		// the batch
   210  		if newBitmap.Bit(int(valIndex)) == 0 {
   211  			newBitmap.SetBit(newBitmap, (int(valIndex)), 1)
   212  			committedSeals = append(committedSeals, commit.CommittedSeal)
   213  		}
   214  	}
   215  
   216  	asig, err := blscrypto.AggregateSignatures(committedSeals)
   217  	if err != nil {
   218  		return types.IstanbulAggregatedSeal{}, err
   219  	}
   220  
   221  	return types.IstanbulAggregatedSeal{
   222  		Bitmap:    newBitmap,
   223  		Signature: asig,
   224  		Round:     aggregatedSignature.Round,
   225  	}, nil
   226  }
   227  
   228  // Appends the current view and state to the given context.
   229  func (c *core) newLogger(ctx ...interface{}) log.Logger {
   230  	var seq, round, desired *big.Int
   231  	var state State
   232  	if c.current != nil {
   233  		state = c.current.State()
   234  		seq = c.current.Sequence()
   235  		round = c.current.Round()
   236  		desired = c.current.DesiredRound()
   237  	} else {
   238  		seq = common.Big0
   239  		round = big.NewInt(-1)
   240  		desired = big.NewInt(-1)
   241  	}
   242  	logger := c.logger.New(ctx...)
   243  	return logger.New("cur_seq", seq, "cur_round", round, "desired_round", desired, "state", state, "address", c.address)
   244  }
   245  
   246  func (c *core) finalizeMessage(msg *istanbul.Message) ([]byte, error) {
   247  	// Add sender address
   248  	msg.Address = c.address
   249  
   250  	if err := msg.Sign(c.backend.Sign); err != nil {
   251  		return nil, err
   252  	}
   253  
   254  	// Convert to payload
   255  	payload, err := msg.Payload()
   256  	if err != nil {
   257  		return nil, err
   258  	}
   259  
   260  	return payload, nil
   261  }
   262  
   263  // Send message to all current validators
   264  func (c *core) broadcast(msg *istanbul.Message) {
   265  	c.sendMsgTo(msg, istanbul.MapValidatorsToAddresses(c.current.ValidatorSet().List()))
   266  }
   267  
   268  // Send message to a specific address
   269  func (c *core) unicast(msg *istanbul.Message, addr common.Address) {
   270  	c.sendMsgTo(msg, []common.Address{addr})
   271  }
   272  
   273  func (c *core) sendMsgTo(msg *istanbul.Message, addresses []common.Address) {
   274  	logger := c.newLogger("func", "sendMsgTo")
   275  
   276  	payload, err := c.finalizeMessage(msg)
   277  	if err != nil {
   278  		logger.Error("Failed to finalize message", "m", msg, "err", err)
   279  		return
   280  	}
   281  
   282  	// Send payload to the specified addresses
   283  	if err := c.backend.BroadcastConsensusMsg(addresses, payload); err != nil {
   284  		logger.Error("Failed to send message", "m", msg, "err", err)
   285  		return
   286  	}
   287  }
   288  
   289  func (c *core) commit() error {
   290  	err := c.current.TransitionToCommitted()
   291  	if err != nil {
   292  		return err
   293  	}
   294  
   295  	// Process Backlog Messages
   296  	c.backlog.updateState(c.current.View(), c.current.State())
   297  
   298  	proposal := c.current.Proposal()
   299  	if proposal != nil {
   300  		aggregatedSeal, err := GetAggregatedSeal(c.current.Commits(), c.current.Round())
   301  		if err != nil {
   302  			nextRound := new(big.Int).Add(c.current.Round(), common.Big1)
   303  			c.logger.Warn("Error on commit, waiting for desired round", "reason", "getAggregatedSeal", "err", err, "desired_round", nextRound)
   304  			c.waitForDesiredRound(nextRound)
   305  			return nil
   306  		}
   307  		aggregatedEpochValidatorSetSeal, err := GetAggregatedEpochValidatorSetSeal(c.current.Commits())
   308  		if err != nil {
   309  			nextRound := new(big.Int).Add(c.current.Round(), common.Big1)
   310  			c.logger.Warn("Error on commit, waiting for desired round", "reason", "GetAggregatedEpochValidatorSetSeal", "err", err, "desired_round", nextRound)
   311  			c.waitForDesiredRound(nextRound)
   312  			return nil
   313  		}
   314  		if err := c.backend.Commit(proposal, aggregatedSeal, aggregatedEpochValidatorSetSeal); err != nil {
   315  			nextRound := new(big.Int).Add(c.current.Round(), common.Big1)
   316  			c.logger.Warn("Error on commit, waiting for desired round", "reason", "backend.Commit", "err", err, "desired_round", nextRound)
   317  			c.waitForDesiredRound(nextRound)
   318  			return nil
   319  		}
   320  	}
   321  	return nil
   322  }
   323  
   324  // GetAggregatedEpochValidatorSetSeal aggregates all the given seals for the SNARK-friendly epoch encoding
   325  // to a bls aggregated signature
   326  func GetAggregatedEpochValidatorSetSeal(seals MessageSet) (types.IstanbulEpochValidatorSetSeal, error) {
   327  	epochSeals := make([][]byte, seals.Size())
   328  	for i, v := range seals.Values() {
   329  		epochSeals[i] = make([]byte, types.IstanbulExtraBlsSignature)
   330  
   331  		var commit *istanbul.CommittedSubject
   332  		err := v.Decode(&commit)
   333  		if err != nil {
   334  			return types.IstanbulEpochValidatorSetSeal{}, err
   335  		}
   336  		copy(epochSeals[i], commit.EpochValidatorSetSeal[:])
   337  	}
   338  
   339  	asig, err := blscrypto.AggregateSignatures(epochSeals)
   340  	if err != nil {
   341  		return types.IstanbulEpochValidatorSetSeal{}, err
   342  	}
   343  	return types.IstanbulEpochValidatorSetSeal{Signature: asig}, nil
   344  }
   345  
   346  // Generates the next preprepare request and associated round change certificate
   347  func (c *core) getPreprepareWithRoundChangeCertificate(round *big.Int) (*istanbul.Request, istanbul.RoundChangeCertificate, error) {
   348  	logger := c.newLogger("func", "getPreprepareWithRoundChangeCertificate", "for_round", round)
   349  
   350  	roundChangeCertificate, err := c.roundChangeSet.getCertificate(round, c.current.ValidatorSet().MinQuorumSize())
   351  	if err != nil {
   352  		return &istanbul.Request{}, istanbul.RoundChangeCertificate{}, err
   353  	}
   354  	// Start with pending request
   355  	request := c.current.PendingRequest()
   356  	// Search for a valid request in round change messages.
   357  	// The proposal must come from the prepared certificate with the highest round number.
   358  	// All prepared certificates from the same round are assumed to be the same proposal or no proposal (guaranteed by quorum intersection)
   359  	maxRound := big.NewInt(-1)
   360  	for _, message := range roundChangeCertificate.RoundChangeMessages {
   361  		var roundChangeMsg *istanbul.RoundChange
   362  		if err := message.Decode(&roundChangeMsg); err != nil {
   363  			logger.Error("Unexpected: could not decode a previously received RoundChange message")
   364  			return &istanbul.Request{}, istanbul.RoundChangeCertificate{}, err
   365  		}
   366  
   367  		if !roundChangeMsg.HasPreparedCertificate() {
   368  			continue
   369  		}
   370  
   371  		preparedCertificateView, err := c.getViewFromVerifiedPreparedCertificate(roundChangeMsg.PreparedCertificate)
   372  		if err != nil {
   373  			logger.Error("Unexpected: could not verify a previously received PreparedCertificate message", "src_m", message)
   374  			return &istanbul.Request{}, istanbul.RoundChangeCertificate{}, err
   375  		}
   376  
   377  		if preparedCertificateView != nil && preparedCertificateView.Round.Cmp(maxRound) > 0 {
   378  			maxRound = preparedCertificateView.Round
   379  			request = &istanbul.Request{
   380  				Proposal: roundChangeMsg.PreparedCertificate.Proposal,
   381  			}
   382  		}
   383  	}
   384  	return request, roundChangeCertificate, nil
   385  }
   386  
   387  // startNewRound starts a new round. if round equals to 0, it means to starts a new sequence
   388  func (c *core) startNewRound(round *big.Int) error {
   389  	logger := c.newLogger("func", "startNewRound", "tag", "stateTransition")
   390  
   391  	roundChange := false
   392  	// Try to get last proposal
   393  	headBlock, headAuthor := c.backend.GetCurrentHeadBlockAndAuthor()
   394  
   395  	if headBlock.Number().Cmp(c.current.Sequence()) >= 0 {
   396  		// Want to be working on the block 1 beyond the last committed block.
   397  		diff := new(big.Int).Sub(headBlock.Number(), c.current.Sequence())
   398  		c.sequenceMeter.Mark(new(big.Int).Add(diff, common.Big1).Int64())
   399  
   400  		if !c.consensusTimestamp.IsZero() {
   401  			c.consensusTimer.UpdateSince(c.consensusTimestamp)
   402  			c.consensusTimestamp = time.Time{}
   403  		}
   404  		logger.Trace("Catch up to the latest proposal.", "number", headBlock.Number().Uint64(), "hash", headBlock.Hash())
   405  	} else if headBlock.Number().Cmp(big.NewInt(c.current.Sequence().Int64()-1)) == 0 {
   406  		// Working on the block immediately after the last committed block.
   407  		if round.Cmp(c.current.Round()) == 0 {
   408  			logger.Trace("Already in the desired round.")
   409  			return nil
   410  		} else if round.Cmp(c.current.Round()) < 0 {
   411  			logger.Warn("New round should not be smaller than current round", "lastBlockNumber", headBlock.Number().Int64(), "new_round", round)
   412  			return nil
   413  		}
   414  		roundChange = true
   415  	} else {
   416  		logger.Warn("New sequence should be larger than current sequence", "new_seq", headBlock.Number().Int64())
   417  		return nil
   418  	}
   419  
   420  	// Generate next view and preprepare
   421  	var newView *istanbul.View
   422  	var roundChangeCertificate istanbul.RoundChangeCertificate
   423  	var request *istanbul.Request
   424  
   425  	valSet := c.current.ValidatorSet()
   426  	if roundChange {
   427  		newView = &istanbul.View{
   428  			Sequence: new(big.Int).Set(c.current.Sequence()),
   429  			Round:    new(big.Int).Set(round),
   430  		}
   431  
   432  		var err error
   433  		request, roundChangeCertificate, err = c.getPreprepareWithRoundChangeCertificate(round)
   434  		if err != nil {
   435  			logger.Error("Unable to produce round change certificate", "err", err, "new_round", round)
   436  			return nil
   437  		}
   438  	} else {
   439  		request = c.current.PendingRequest()
   440  		newView = &istanbul.View{
   441  			Sequence: new(big.Int).Add(headBlock.Number(), common.Big1),
   442  			Round:    new(big.Int),
   443  		}
   444  		valSet = c.backend.Validators(headBlock)
   445  		c.roundChangeSet = newRoundChangeSet(valSet)
   446  	}
   447  
   448  	logger = logger.New("old_proposer", c.current.Proposer())
   449  
   450  	// Calculate new proposer
   451  	nextProposer := c.selectProposer(valSet, headAuthor, newView.Round.Uint64())
   452  	err := c.resetRoundState(newView, valSet, nextProposer, roundChange)
   453  
   454  	if err != nil {
   455  		return err
   456  	}
   457  
   458  	// Process backlog
   459  	c.processPendingRequests()
   460  	c.backlog.updateState(c.current.View(), c.current.State())
   461  
   462  	if roundChange && c.isProposer() && request != nil {
   463  		c.sendPreprepare(request, roundChangeCertificate)
   464  	}
   465  	c.resetRoundChangeTimer()
   466  
   467  	logger.Debug("New round", "new_round", newView.Round, "new_seq", newView.Sequence, "new_proposer", c.current.Proposer(), "valSet", c.current.ValidatorSet().List(), "size", c.current.ValidatorSet().Size(), "isProposer", c.isProposer())
   468  	return nil
   469  }
   470  
   471  // All actions that occur when transitioning to waiting for round change state.
   472  func (c *core) waitForDesiredRound(r *big.Int) error {
   473  	logger := c.newLogger("func", "waitForDesiredRound", "old_desired_round", c.current.DesiredRound(), "new_desired_round", r)
   474  
   475  	// Don't wait for an older round
   476  	if c.current.DesiredRound().Cmp(r) >= 0 {
   477  		logger.Trace("New desired round not greater than current desired round")
   478  		return nil
   479  	}
   480  
   481  	logger.Debug("Round Change: Waiting for desired round")
   482  
   483  	// Perform all of the updates
   484  	_, headAuthor := c.backend.GetCurrentHeadBlockAndAuthor()
   485  	nextProposer := c.selectProposer(c.current.ValidatorSet(), headAuthor, r.Uint64())
   486  	err := c.current.TransitionToWaitingForNewRound(r, nextProposer)
   487  	if err != nil {
   488  		return err
   489  	}
   490  
   491  	c.resetRoundChangeTimer()
   492  
   493  	// Process Backlog Messages
   494  	c.backlog.updateState(c.current.View(), c.current.State())
   495  
   496  	// Send round change
   497  	c.sendRoundChange()
   498  	return nil
   499  }
   500  
   501  func (c *core) createRoundState() (RoundState, error) {
   502  	var roundState RoundState
   503  
   504  	logger := c.newLogger("func", "createRoundState")
   505  
   506  	if c.current != nil {
   507  		return nil, fmt.Errorf("BUG? Attempting to Start() core with existing c.current")
   508  	}
   509  
   510  	headBlock, headAuthor := c.backend.GetCurrentHeadBlockAndAuthor()
   511  	nextSequence := new(big.Int).Add(headBlock.Number(), common.Big1)
   512  	lastStoredView, err := c.rsdb.GetLastView()
   513  
   514  	if err != nil && err != leveldb.ErrNotFound {
   515  		logger.Error("Failed to fetch lastStoredView", "err", err)
   516  		return nil, err
   517  	}
   518  
   519  	if err == leveldb.ErrNotFound || lastStoredView.Sequence.Cmp(nextSequence) < 0 {
   520  		if err == leveldb.ErrNotFound {
   521  			logger.Info("Creating new RoundState", "reason", "No storedView found")
   522  		} else {
   523  			logger.Info("Creating new RoundState", "reason", "old view", "stored_view", lastStoredView, "requested_seq", nextSequence)
   524  		}
   525  		valSet := c.backend.Validators(headBlock)
   526  		proposer := c.selectProposer(valSet, headAuthor, 0)
   527  		roundState = newRoundState(&istanbul.View{Sequence: nextSequence, Round: common.Big0}, valSet, proposer)
   528  	} else {
   529  		logger.Info("Retrieving stored RoundState", "stored_view", lastStoredView, "requested_seq", nextSequence)
   530  		roundState, err = c.rsdb.GetRoundStateFor(lastStoredView)
   531  
   532  		if err != nil {
   533  			logger.Error("Failed to fetch lastStoredRoundState", "err", err)
   534  			return nil, err
   535  		}
   536  	}
   537  
   538  	return withSavingDecorator(c.rsdb, roundState), nil
   539  }
   540  
   541  // resetRoundState will modify the RoundState to either start a new round or a new sequence
   542  // based on the `roundChange` flag given
   543  func (c *core) resetRoundState(view *istanbul.View, validatorSet istanbul.ValidatorSet, nextProposer istanbul.Validator, roundChange bool) error {
   544  	// TODO(Joshua): Include desired round here.
   545  	if roundChange {
   546  		return c.current.StartNewRound(view.Round, validatorSet, nextProposer)
   547  	}
   548  
   549  	// sequence change
   550  	// TODO remove this when we refactor startNewRound()
   551  	if view.Round.Cmp(common.Big0) != 0 {
   552  		c.logger.Crit("BUG: DevError: trying to start a new sequence with round != 0", "wanted_round", view.Round)
   553  	}
   554  
   555  	var newParentCommits MessageSet
   556  	lastSubject, err := c.backend.LastSubject()
   557  	if err == nil && c.current.Proposal() != nil && c.current.Proposal().Hash() == lastSubject.Digest && c.current.Round().Cmp(lastSubject.View.Round) == 0 {
   558  		// When changing sequences, if our current Commit messages match the latest block in the chain
   559  		// (i.e. they're for the same block hash and round), we use this sequence's commits as the ParentCommits field
   560  		// in the next round.
   561  		newParentCommits = c.current.Commits()
   562  	} else {
   563  		// Otherwise, we will initialize an empty ParentCommits field with the validator set of the last proposal.
   564  		headBlock := c.backend.GetCurrentHeadBlock()
   565  		newParentCommits = newMessageSet(c.backend.ParentBlockValidators(headBlock))
   566  	}
   567  	return c.current.StartNewSequence(view.Sequence, validatorSet, nextProposer, newParentCommits)
   568  
   569  }
   570  
   571  func (c *core) isProposer() bool {
   572  	if c.current == nil {
   573  		return false
   574  	}
   575  	return c.current.IsProposer(c.address)
   576  }
   577  
   578  func (c *core) stopFuturePreprepareTimer() {
   579  	if c.futurePreprepareTimer != nil {
   580  		c.futurePreprepareTimer.Stop()
   581  		c.futurePreprepareTimer = nil
   582  	}
   583  }
   584  
   585  func (c *core) stopRoundChangeTimer() {
   586  	if c.roundChangeTimer != nil {
   587  		c.roundChangeTimer.Stop()
   588  		c.roundChangeTimer = nil
   589  	}
   590  }
   591  
   592  func (c *core) stopResendRoundChangeTimer() {
   593  	if c.resendRoundChangeMessageTimer != nil {
   594  		c.resendRoundChangeMessageTimer.Stop()
   595  		c.resendRoundChangeMessageTimer = nil
   596  	}
   597  }
   598  
   599  func (c *core) stopAllTimers() {
   600  	c.stopFuturePreprepareTimer()
   601  	c.stopRoundChangeTimer()
   602  	c.stopResendRoundChangeTimer()
   603  }
   604  
   605  func (c *core) getRoundChangeTimeout() time.Duration {
   606  	baseTimeout := time.Duration(c.config.RequestTimeout) * time.Millisecond
   607  	round := c.current.DesiredRound().Uint64()
   608  	if round == 0 {
   609  		// timeout for first round takes into account expected block period
   610  		return baseTimeout + time.Duration(c.config.BlockPeriod)*time.Second
   611  	} else {
   612  		// timeout for subsequent rounds adds an exponential backoff.
   613  		return baseTimeout + time.Duration(math.Pow(2, float64(round)))*time.Duration(c.config.TimeoutBackoffFactor)*time.Millisecond
   614  	}
   615  }
   616  
   617  // Reset then set the timer that causes a timeoutAndMoveToNextRoundEvent to be processed.
   618  // This may also reset the timer for the next resendRoundChangeEvent.
   619  func (c *core) resetRoundChangeTimer() {
   620  	// Stop all timers here since all 'resends' happen within the interval of a round's timeout.
   621  	// (Races are handled anyway by checking the seq and desired round haven't changed between
   622  	// submitting and processing events).
   623  	c.stopAllTimers()
   624  
   625  	view := &istanbul.View{Sequence: c.current.Sequence(), Round: c.current.DesiredRound()}
   626  	timeout := c.getRoundChangeTimeout()
   627  	c.roundChangeTimer = time.AfterFunc(timeout, func() {
   628  		c.sendEvent(timeoutAndMoveToNextRoundEvent{view})
   629  	})
   630  
   631  	if c.current.DesiredRound().Cmp(common.Big1) > 0 {
   632  		logger := c.newLogger("func", "resetRoundChangeTimer")
   633  		logger.Info("Reset round change timer", "timeout_ms", timeout/time.Millisecond)
   634  	}
   635  
   636  	c.resetResendRoundChangeTimer()
   637  }
   638  
   639  // Reset then, if in StateWaitingForNewRound and on round whose timeout is greater than MinResendRoundChangeTimeout,
   640  // set a timer that is at most MaxResendRoundChangeTimeout that causes a resendRoundChangeEvent to be processed.
   641  func (c *core) resetResendRoundChangeTimer() {
   642  	c.stopResendRoundChangeTimer()
   643  	if c.current.State() == StateWaitingForNewRound {
   644  		minResendTimeout := time.Duration(c.config.MinResendRoundChangeTimeout) * time.Millisecond
   645  		resendTimeout := c.getRoundChangeTimeout() / 2
   646  		if resendTimeout < minResendTimeout {
   647  			return
   648  		}
   649  		maxResendTimeout := time.Duration(c.config.MaxResendRoundChangeTimeout) * time.Millisecond
   650  		if resendTimeout > maxResendTimeout {
   651  			resendTimeout = maxResendTimeout
   652  		}
   653  		view := &istanbul.View{Sequence: c.current.Sequence(), Round: c.current.DesiredRound()}
   654  		c.resendRoundChangeMessageTimer = time.AfterFunc(resendTimeout, func() {
   655  			c.sendEvent(resendRoundChangeEvent{view})
   656  		})
   657  	}
   658  }
   659  
   660  // Rebroadcast RoundChange message for desired round if still in StateWaitingForNewRound.
   661  // Do not advance desired round. Then clear/reset timer so we may rebroadcast again.
   662  func (c *core) resendRoundChangeMessage() {
   663  	if c.current.State() == StateWaitingForNewRound {
   664  		c.sendRoundChange()
   665  	}
   666  	c.resetResendRoundChangeTimer()
   667  }
   668  
   669  func (c *core) checkValidatorSignature(data []byte, sig []byte) (common.Address, error) {
   670  	return istanbul.CheckValidatorSignature(c.current.ValidatorSet(), data, sig)
   671  }
   672  
   673  func (c *core) verifyProposal(proposal istanbul.Proposal) (time.Duration, error) {
   674  	logger := c.newLogger("func", "verifyProposal", "proposal", proposal.Hash())
   675  	if verificationStatus, isCached := c.current.GetProposalVerificationStatus(proposal.Hash()); isCached {
   676  		logger.Trace("verification status cache hit", "verificationStatus", verificationStatus)
   677  		return 0, verificationStatus
   678  	} else {
   679  		logger.Trace("verification status cache miss")
   680  
   681  		duration, err := c.backend.Verify(proposal)
   682  		logger.Trace("proposal verify return values", "duration", duration, "err", err)
   683  
   684  		// Don't cache the verification status if it's a future block
   685  		if err != consensus.ErrFutureBlock {
   686  			c.current.SetProposalVerificationStatus(proposal.Hash(), err)
   687  		}
   688  
   689  		return duration, err
   690  	}
   691  }