diff options
Diffstat (limited to 'consensus/clique/clique.go')
-rw-r--r-- | consensus/clique/clique.go | 50 |
1 files changed, 28 insertions, 22 deletions
diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 87a983377..d2fb6934b 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -76,7 +76,7 @@ var ( errUnknownBlock = errors.New("unknown block") // errInvalidCheckpointBeneficiary is returned if a checkpoint/epoch transition - // block has a beneficiary set to non zeroes. + // block has a beneficiary set to non-zeroes. errInvalidCheckpointBeneficiary = errors.New("beneficiary in checkpoint block non-zero") // errInvalidVote is returned if a nonce value is something else that the two @@ -84,7 +84,7 @@ var ( errInvalidVote = errors.New("vote nonce not 0x00..0 or 0xff..f") // errInvalidCheckpointVote is returned if a checkpoint/epoch transition block - // has a vote nonce set to non zeroes. + // has a vote nonce set to non-zeroes. errInvalidCheckpointVote = errors.New("vote nonce in checkpoint block non-zero") // errMissingVanity is returned if a block's extra-data section is shorter than @@ -99,12 +99,12 @@ var ( // their extra-data fields. errExtraSigners = errors.New("non-checkpoint block contains extra signer list") - // drrInvalidCheckpointSigners is returned if a checkpoint block contains an + // errInvalidCheckpointSigners is returned if a checkpoint block contains an // invalid list of signers (i.e. non divisible by 20 bytes, or not the correct // ones). - drrInvalidCheckpointSigners = errors.New("invalid signer list on checkpoint block") + errInvalidCheckpointSigners = errors.New("invalid signer list on checkpoint block") - // errInvalidMixDigest is returned if a block's mix digest is non zero. + // errInvalidMixDigest is returned if a block's mix digest is non-zero. errInvalidMixDigest = errors.New("non-zero mix digest") // errInvalidUncleHash is returned if a block contains an non-empty uncle list. @@ -122,7 +122,7 @@ var ( // be modified via out-of-range or non-contiguous headers. errInvalidVotingChain = errors.New("invalid voting chain") - // errUnauthorized is returned if a header is signed by a non authorized entity. + // errUnauthorized is returned if a header is signed by a non-authorized entity. errUnauthorized = errors.New("unauthorized") ) @@ -297,7 +297,7 @@ func (c *Clique) verifyHeader(chain consensus.ChainReader, header *types.Header, return errExtraSigners } if checkpoint && signersBytes%common.AddressLength != 0 { - return drrInvalidCheckpointSigners + return errInvalidCheckpointSigners } // Ensure that the mix digest is zero as we don't have fork protection currently if header.MixDigest != (common.Hash{}) { @@ -353,7 +353,7 @@ func (c *Clique) verifyCascadingFields(chain consensus.ChainReader, header *type } extraSuffix := len(header.Extra) - extraSeal if !bytes.Equal(header.Extra[extraVanity:extraSuffix], signers) { - return drrInvalidCheckpointSigners + return errInvalidCheckpointSigners } } // All basic checks passed, verify the seal and return @@ -467,7 +467,6 @@ func (c *Clique) verifySeal(chain consensus.ChainReader, header *types.Header, p if err != nil { return err } - c.recents.Add(snap.Hash, snap) // Resolve the authorization key and check against signers signer, err := ecrecover(header, c.signatures) @@ -479,13 +478,13 @@ func (c *Clique) verifySeal(chain consensus.ChainReader, header *types.Header, p } for seen, recent := range snap.Recents { if recent == signer { - // Signer is among recents, only fail if the current block doens't shift it out + // Signer is among recents, only fail if the current block doesn't shift it out if limit := uint64(len(snap.Signers)/2 + 1); seen > number-limit { return errUnauthorized } } } - // Ensure that the difficulty corresponts to the turn-ness of the signer + // Ensure that the difficulty corresponds to the turn-ness of the signer inturn := snap.inturn(header.Number.Uint64(), signer) if inturn && header.Difficulty.Cmp(diffInTurn) != 0 { return errInvalidDifficulty @@ -499,18 +498,29 @@ func (c *Clique) verifySeal(chain consensus.ChainReader, header *types.Header, p // Prepare implements consensus.Engine, preparing all the consensus fields of the // header for running the transactions on top. func (c *Clique) Prepare(chain consensus.ChainReader, header *types.Header) error { - // If the block isn't a checkpoint, cast a random vote (good enough fror now) + // If the block isn't a checkpoint, cast a random vote (good enough for now) header.Coinbase = common.Address{} header.Nonce = types.BlockNonce{} number := header.Number.Uint64() + + // Assemble the voting snapshot to check which votes make sense + snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) + if err != nil { + return err + } if number%c.config.Epoch != 0 { c.lock.RLock() - if len(c.proposals) > 0 { - addresses := make([]common.Address, 0, len(c.proposals)) - for address := range c.proposals { + + // Gather all the proposals that make sense voting on + addresses := make([]common.Address, 0, len(c.proposals)) + for address, authorize := range c.proposals { + if snap.validVote(address, authorize) { addresses = append(addresses, address) } + } + // If there's pending proposals, cast a vote on them + if len(addresses) > 0 { header.Coinbase = addresses[rand.Intn(len(addresses))] if c.proposals[header.Coinbase] { copy(header.Nonce[:], nonceAuthVote) @@ -520,11 +530,7 @@ func (c *Clique) Prepare(chain consensus.ChainReader, header *types.Header) erro } c.lock.RUnlock() } - // Assemble the voting snapshot and set the correct difficulty - snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) - if err != nil { - return err - } + // Set the correct difficulty header.Difficulty = diffNoTurn if snap.inturn(header.Number.Uint64(), c.signer) { header.Difficulty = diffInTurn @@ -601,10 +607,10 @@ func (c *Clique) Seal(chain consensus.ChainReader, block *types.Block, stop <-ch if _, authorized := snap.Signers[signer]; !authorized { return nil, errUnauthorized } - // If we're amongs the recent signers, wait for the next block + // If we're amongst the recent signers, wait for the next block for seen, recent := range snap.Recents { if recent == signer { - // Signer is among recents, only wait if the current block doens't shift it out + // Signer is among recents, only wait if the current block doesn't shift it out if limit := uint64(len(snap.Signers)/2 + 1); number < limit || seen > number-limit { log.Info("Signed recently, must wait for others") <-stop |