|
|
|
|
@ -56,13 +56,7 @@ var (
|
|
|
|
|
extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity
|
|
|
|
|
extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal
|
|
|
|
|
|
|
|
|
|
nonceAuthVote = hexutil.MustDecode("0xffffffffffffffff") // Magic nonce number to vote on adding a new signer
|
|
|
|
|
nonceDropVote = hexutil.MustDecode("0x0000000000000000") // Magic nonce number to vote on removing a signer.
|
|
|
|
|
|
|
|
|
|
uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW.
|
|
|
|
|
|
|
|
|
|
diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures
|
|
|
|
|
diffNoTurn = big.NewInt(1) // Block difficulty for out-of-turn signatures
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Various error messages to mark blocks invalid. These should be private to
|
|
|
|
|
@ -98,6 +92,10 @@ var (
|
|
|
|
|
// their extra-data fields.
|
|
|
|
|
errExtraSigners = errors.New("non-checkpoint block contains extra signer list")
|
|
|
|
|
|
|
|
|
|
// errInvalidValidatorSeal is returned if the extra data field length is not
|
|
|
|
|
// equal to the length of a seal
|
|
|
|
|
errInvalidExtraData = errors.New("extra data field in block header is invalid")
|
|
|
|
|
|
|
|
|
|
// 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).
|
|
|
|
|
@ -193,7 +191,7 @@ func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, er
|
|
|
|
|
// Clique is the proof-of-authority consensus engine proposed to support the
|
|
|
|
|
// Ethereum testnet following the Ropsten attacks.
|
|
|
|
|
type Aura struct {
|
|
|
|
|
config *params.CliqueConfig // Consensus engine configuration parameters
|
|
|
|
|
config *params.AuraConfig // Consensus engine configuration parameters
|
|
|
|
|
db ethdb.Database // Database to store and retrieve snapshot checkpoints
|
|
|
|
|
|
|
|
|
|
recents *lru.ARCCache // Snapshots for recent block to speed up reorgs
|
|
|
|
|
@ -206,9 +204,9 @@ type Aura struct {
|
|
|
|
|
lock sync.RWMutex // Protects the signer fields
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// New creates a Clique proof-of-authority consensus engine with the initial
|
|
|
|
|
// New creates a Aura proof-of-authority consensus engine with the initial
|
|
|
|
|
// signers set to the ones provided by the user.
|
|
|
|
|
func New(config *params.CliqueConfig, db ethdb.Database) *Clique {
|
|
|
|
|
func New(config *params.AuraConfig, db ethdb.Database) *Aura {
|
|
|
|
|
// Set any missing consensus parameters to their defaults
|
|
|
|
|
conf := *config
|
|
|
|
|
if conf.Epoch == 0 {
|
|
|
|
|
@ -229,25 +227,25 @@ func New(config *params.CliqueConfig, db ethdb.Database) *Clique {
|
|
|
|
|
|
|
|
|
|
// Author implements consensus.Engine, returning the Ethereum address recovered
|
|
|
|
|
// from the signature in the header's extra-data section.
|
|
|
|
|
func (c *Aura) Author(header *types.Header) (common.Address, error) {
|
|
|
|
|
return ecrecover(header, c.signatures)
|
|
|
|
|
func (a *Aura) Author(header *types.Header) (common.Address, error) {
|
|
|
|
|
return ecrecover(header, a.signatures)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// VerifyHeader checks whether a header conforms to the consensus rules.
|
|
|
|
|
func (c *Aura) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error {
|
|
|
|
|
return c.verifyHeader(chain, header, nil)
|
|
|
|
|
func (a *Aura) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error {
|
|
|
|
|
return a.verifyHeader(chain, header, nil)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The
|
|
|
|
|
// method returns a quit channel to abort the operations and a results channel to
|
|
|
|
|
// retrieve the async verifications (the order is that of the input slice).
|
|
|
|
|
func (c *Aura) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
|
|
|
|
|
func (a *Aura) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
|
|
|
|
|
abort := make(chan struct{})
|
|
|
|
|
results := make(chan error, len(headers))
|
|
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
|
for i, header := range headers {
|
|
|
|
|
err := c.verifyHeader(chain, header, headers[:i])
|
|
|
|
|
err := a.verifyHeader(chain, header, headers[:i])
|
|
|
|
|
|
|
|
|
|
select {
|
|
|
|
|
case <-abort:
|
|
|
|
|
@ -263,7 +261,7 @@ func (c *Aura) VerifyHeaders(chain consensus.ChainReader, headers []*types.Heade
|
|
|
|
|
// caller may optionally pass in a batch of parents (ascending order) to avoid
|
|
|
|
|
// looking those up from the database. This is useful for concurrently verifying
|
|
|
|
|
// a batch of new headers.
|
|
|
|
|
func (c *Aura) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
|
|
|
|
|
func (a *Aura) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
|
|
|
|
|
if header.Number == nil {
|
|
|
|
|
return errUnknownBlock
|
|
|
|
|
}
|
|
|
|
|
@ -273,32 +271,21 @@ func (c *Aura) verifyHeader(chain consensus.ChainReader, header *types.Header, p
|
|
|
|
|
if header.Time.Cmp(big.NewInt(time.Now().Unix())) > 0 {
|
|
|
|
|
return consensus.ErrFutureBlock
|
|
|
|
|
}
|
|
|
|
|
// TODO: Are any of these necessary checks?
|
|
|
|
|
// Checkpoint blocks need to enforce zero beneficiary
|
|
|
|
|
checkpoint := (number % c.config.Epoch) == 0
|
|
|
|
|
if checkpoint && header.Coinbase != (common.Address{}) {
|
|
|
|
|
return errInvalidCheckpointBeneficiary
|
|
|
|
|
}
|
|
|
|
|
//checkpoint := (number % a.config.Epoch) == 0
|
|
|
|
|
//if checkpoint && header.Coinbase != (common.Address{}) {
|
|
|
|
|
// return errInvalidCheckpointBeneficiary
|
|
|
|
|
//}
|
|
|
|
|
// Nonces must be 0x00..0 or 0xff..f, zeroes enforced on checkpoints
|
|
|
|
|
if !bytes.Equal(header.Nonce[:], nonceAuthVote) && !bytes.Equal(header.Nonce[:], nonceDropVote) {
|
|
|
|
|
return errInvalidVote
|
|
|
|
|
}
|
|
|
|
|
if checkpoint && !bytes.Equal(header.Nonce[:], nonceDropVote) {
|
|
|
|
|
return errInvalidCheckpointVote
|
|
|
|
|
}
|
|
|
|
|
// Check that the extra-data contains both the vanity and signature
|
|
|
|
|
if len(header.Extra) < extraVanity {
|
|
|
|
|
return errMissingVanity
|
|
|
|
|
}
|
|
|
|
|
if len(header.Extra) < extraVanity+extraSeal {
|
|
|
|
|
return errMissingSignature
|
|
|
|
|
}
|
|
|
|
|
// Ensure that the extra-data contains a signer list on checkpoint, but none otherwise
|
|
|
|
|
signersBytes := len(header.Extra) - extraVanity - extraSeal
|
|
|
|
|
if !checkpoint && signersBytes != 0 {
|
|
|
|
|
return errExtraSigners
|
|
|
|
|
}
|
|
|
|
|
if checkpoint && signersBytes%common.AddressLength != 0 {
|
|
|
|
|
return errInvalidCheckpointSigners
|
|
|
|
|
//if !bytes.Equal(header.Nonce[:], nonceAuthVote) && !bytes.Equal(header.Nonce[:], nonceDropVote) {
|
|
|
|
|
// return errInvalidVote
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
// Ensure that the extra-data contains a single signature
|
|
|
|
|
signersBytes := len(header.Extra) - extraSeal
|
|
|
|
|
if signersBytes != 0 {
|
|
|
|
|
return errInvalidExtraData
|
|
|
|
|
}
|
|
|
|
|
// Ensure that the mix digest is zero as we don't have fork protection currently
|
|
|
|
|
if header.MixDigest != (common.Hash{}) {
|
|
|
|
|
@ -308,9 +295,9 @@ func (c *Aura) verifyHeader(chain consensus.ChainReader, header *types.Header, p
|
|
|
|
|
if header.UncleHash != uncleHash {
|
|
|
|
|
return errInvalidUncleHash
|
|
|
|
|
}
|
|
|
|
|
// Ensure that the block's difficulty is meaningful (may not be correct at this point)
|
|
|
|
|
// Ensure that the block's difficulty is correct (it should be constant)
|
|
|
|
|
if number > 0 {
|
|
|
|
|
if header.Difficulty == nil || (header.Difficulty.Cmp(diffInTurn) != 0 && header.Difficulty.Cmp(diffNoTurn) != 0) {
|
|
|
|
|
if header.Difficulty != chain.Config().Difficulty {
|
|
|
|
|
return errInvalidDifficulty
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -319,14 +306,14 @@ func (c *Aura) verifyHeader(chain consensus.ChainReader, header *types.Header, p
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
// All basic checks passed, verify cascading fields
|
|
|
|
|
return c.verifyCascadingFields(chain, header, parents)
|
|
|
|
|
return a.verifyCascadingFields(chain, header, parents)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// verifyCascadingFields verifies all the header fields that are not standalone,
|
|
|
|
|
// rather depend on a batch of previous headers. The caller may optionally pass
|
|
|
|
|
// in a batch of parents (ascending order) to avoid looking those up from the
|
|
|
|
|
// database. This is useful for concurrently verifying a batch of new headers.
|
|
|
|
|
func (c *Aura) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
|
|
|
|
|
func (a *Aura) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
|
|
|
|
|
// The genesis block is the always valid dead-end
|
|
|
|
|
number := header.Number.Uint64()
|
|
|
|
|
if number == 0 {
|
|
|
|
|
@ -342,16 +329,16 @@ func (c *Aura) verifyCascadingFields(chain consensus.ChainReader, header *types.
|
|
|
|
|
if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash {
|
|
|
|
|
return consensus.ErrUnknownAncestor
|
|
|
|
|
}
|
|
|
|
|
if parent.Time.Uint64()+c.config.Period > header.Time.Uint64() {
|
|
|
|
|
if parent.Time.Uint64()+a.config.Period > header.Time.Uint64() {
|
|
|
|
|
return ErrInvalidTimestamp
|
|
|
|
|
}
|
|
|
|
|
// Retrieve the snapshot needed to verify this header and cache it
|
|
|
|
|
snap, err := c.snapshot(chain, number-1, header.ParentHash, parents)
|
|
|
|
|
snap, err := a.snapshot(chain, number-1, header.ParentHash, parents)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
// If the block is a checkpoint block, verify the signer list
|
|
|
|
|
if number%c.config.Epoch == 0 {
|
|
|
|
|
if number%a.config.Epoch == 0 {
|
|
|
|
|
signers := make([]byte, len(snap.Signers)*common.AddressLength)
|
|
|
|
|
for i, signer := range snap.signers() {
|
|
|
|
|
copy(signers[i*common.AddressLength:], signer[:])
|
|
|
|
|
@ -362,11 +349,11 @@ func (c *Aura) verifyCascadingFields(chain consensus.ChainReader, header *types.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// All basic checks passed, verify the seal and return
|
|
|
|
|
return c.verifySeal(chain, header, parents)
|
|
|
|
|
return a.verifySeal(chain, header, parents)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// snapshot retrieves the authorization snapshot at a given point in time.
|
|
|
|
|
func (c *Aura) snapshot(chain consensus.ChainReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) {
|
|
|
|
|
func (a *Aura) snapshot(chain consensus.ChainReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) {
|
|
|
|
|
// Search for a snapshot in memory or on disk for checkpoints
|
|
|
|
|
var (
|
|
|
|
|
headers []*types.Header
|
|
|
|
|
@ -374,20 +361,20 @@ func (c *Aura) snapshot(chain consensus.ChainReader, number uint64, hash common.
|
|
|
|
|
)
|
|
|
|
|
for snap == nil {
|
|
|
|
|
// If an in-memory snapshot was found, use that
|
|
|
|
|
if s, ok := c.recents.Get(hash); ok {
|
|
|
|
|
if s, ok := a.recents.Get(hash); ok {
|
|
|
|
|
snap = s.(*Snapshot)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
// If an on-disk checkpoint snapshot can be found, use that
|
|
|
|
|
if number%checkpointInterval == 0 {
|
|
|
|
|
if s, err := loadSnapshot(c.config, c.signatures, c.db, hash); err == nil {
|
|
|
|
|
if s, err := loadSnapshot(a.config, a.signatures, a.db, hash); err == nil {
|
|
|
|
|
log.Trace("Loaded voting snapshot from disk", "number", number, "hash", hash)
|
|
|
|
|
snap = s
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// If we're at an checkpoint block, make a snapshot if it's known
|
|
|
|
|
if number%c.config.Epoch == 0 {
|
|
|
|
|
if number%a.config.Epoch == 0 {
|
|
|
|
|
checkpoint := chain.GetHeaderByNumber(number)
|
|
|
|
|
if checkpoint != nil {
|
|
|
|
|
hash := checkpoint.Hash()
|
|
|
|
|
@ -396,8 +383,8 @@ func (c *Aura) snapshot(chain consensus.ChainReader, number uint64, hash common.
|
|
|
|
|
for i := 0; i < len(signers); i++ {
|
|
|
|
|
copy(signers[i][:], checkpoint.Extra[extraVanity+i*common.AddressLength:])
|
|
|
|
|
}
|
|
|
|
|
snap = newSnapshot(c.config, c.signatures, number, hash, signers)
|
|
|
|
|
if err := snap.store(c.db); err != nil {
|
|
|
|
|
snap = newSnapshot(a.config, a.signatures, number, hash, signers)
|
|
|
|
|
if err := snap.store(a.db); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash)
|
|
|
|
|
@ -431,11 +418,11 @@ func (c *Aura) snapshot(chain consensus.ChainReader, number uint64, hash common.
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
c.recents.Add(snap.Hash, snap)
|
|
|
|
|
a.recents.Add(snap.Hash, snap)
|
|
|
|
|
|
|
|
|
|
// If we've generated a new checkpoint snapshot, save to disk
|
|
|
|
|
if snap.Number%checkpointInterval == 0 && len(headers) > 0 {
|
|
|
|
|
if err = snap.store(c.db); err != nil {
|
|
|
|
|
if err = snap.store(a.db); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
log.Trace("Stored voting snapshot to disk", "number", snap.Number, "hash", snap.Hash)
|
|
|
|
|
@ -445,7 +432,7 @@ func (c *Aura) snapshot(chain consensus.ChainReader, number uint64, hash common.
|
|
|
|
|
|
|
|
|
|
// VerifyUncles implements consensus.Engine, always returning an error for any
|
|
|
|
|
// uncles as this consensus mechanism doesn't permit uncles.
|
|
|
|
|
func (c *Aura) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
|
|
|
|
|
func (a *Aura) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
|
|
|
|
|
if len(block.Uncles()) > 0 {
|
|
|
|
|
return errors.New("uncles not allowed")
|
|
|
|
|
}
|
|
|
|
|
@ -454,28 +441,28 @@ func (c *Aura) VerifyUncles(chain consensus.ChainReader, block *types.Block) err
|
|
|
|
|
|
|
|
|
|
// VerifySeal implements consensus.Engine, checking whether the signature contained
|
|
|
|
|
// in the header satisfies the consensus protocol requirements.
|
|
|
|
|
func (c *Aura) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
|
|
|
|
|
return c.verifySeal(chain, header, nil)
|
|
|
|
|
func (a *Aura) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
|
|
|
|
|
return a.verifySeal(chain, header, nil)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// verifySeal checks whether the signature contained in the header satisfies the
|
|
|
|
|
// consensus protocol requirements. The method accepts an optional list of parent
|
|
|
|
|
// headers that aren't yet part of the local blockchain to generate the snapshots
|
|
|
|
|
// from.
|
|
|
|
|
func (c *Aura) verifySeal(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
|
|
|
|
|
func (a *Aura) verifySeal(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
|
|
|
|
|
// Verifying the genesis block is not supported
|
|
|
|
|
number := header.Number.Uint64()
|
|
|
|
|
if number == 0 {
|
|
|
|
|
return errUnknownBlock
|
|
|
|
|
}
|
|
|
|
|
// Retrieve the snapshot needed to verify this header and cache it
|
|
|
|
|
snap, err := c.snapshot(chain, number-1, header.ParentHash, parents)
|
|
|
|
|
snap, err := a.snapshot(chain, number-1, header.ParentHash, parents)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Resolve the authorization key and check against signers
|
|
|
|
|
signer, err := ecrecover(header, c.signatures)
|
|
|
|
|
signer, err := ecrecover(header, a.signatures)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
@ -503,23 +490,23 @@ func (c *Aura) verifySeal(chain consensus.ChainReader, header *types.Header, par
|
|
|
|
|
|
|
|
|
|
// Prepare implements consensus.Engine, preparing all the consensus fields of the
|
|
|
|
|
// header for running the transactions on top.
|
|
|
|
|
func (c *Aura) Prepare(chain consensus.ChainReader, header *types.Header) error {
|
|
|
|
|
func (a *Aura) Prepare(chain consensus.ChainReader, header *types.Header) error {
|
|
|
|
|
// 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)
|
|
|
|
|
snap, err := a.snapshot(chain, number-1, header.ParentHash, nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if number%c.config.Epoch != 0 {
|
|
|
|
|
c.lock.RLock()
|
|
|
|
|
if number%a.config.Epoch != 0 {
|
|
|
|
|
a.lock.RLock()
|
|
|
|
|
|
|
|
|
|
// Gather all the proposals that make sense voting on
|
|
|
|
|
addresses := make([]common.Address, 0, len(c.proposals))
|
|
|
|
|
for address, authorize := range c.proposals {
|
|
|
|
|
addresses := make([]common.Address, 0, len(a.proposals))
|
|
|
|
|
for address, authorize := range a.proposals {
|
|
|
|
|
if snap.validVote(address, authorize) {
|
|
|
|
|
addresses = append(addresses, address)
|
|
|
|
|
}
|
|
|
|
|
@ -527,16 +514,16 @@ func (c *Aura) Prepare(chain consensus.ChainReader, header *types.Header) error
|
|
|
|
|
// 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] {
|
|
|
|
|
if a.proposals[header.Coinbase] {
|
|
|
|
|
copy(header.Nonce[:], nonceAuthVote)
|
|
|
|
|
} else {
|
|
|
|
|
copy(header.Nonce[:], nonceDropVote)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
c.lock.RUnlock()
|
|
|
|
|
a.lock.RUnlock()
|
|
|
|
|
}
|
|
|
|
|
// Set the correct difficulty
|
|
|
|
|
header.Difficulty = CalcDifficulty(snap, c.signer)
|
|
|
|
|
header.Difficulty = CalcDifficulty(snap, a.signer)
|
|
|
|
|
|
|
|
|
|
// Ensure the extra data has all it's components
|
|
|
|
|
if len(header.Extra) < extraVanity {
|
|
|
|
|
@ -544,7 +531,7 @@ func (c *Aura) Prepare(chain consensus.ChainReader, header *types.Header) error
|
|
|
|
|
}
|
|
|
|
|
header.Extra = header.Extra[:extraVanity]
|
|
|
|
|
|
|
|
|
|
if number%c.config.Epoch == 0 {
|
|
|
|
|
if number%a.config.Epoch == 0 {
|
|
|
|
|
for _, signer := range snap.signers() {
|
|
|
|
|
header.Extra = append(header.Extra, signer[:]...)
|
|
|
|
|
}
|
|
|
|
|
@ -559,7 +546,7 @@ func (c *Aura) Prepare(chain consensus.ChainReader, header *types.Header) error
|
|
|
|
|
if parent == nil {
|
|
|
|
|
return consensus.ErrUnknownAncestor
|
|
|
|
|
}
|
|
|
|
|
header.Time = new(big.Int).Add(parent.Time, new(big.Int).SetUint64(c.config.Period))
|
|
|
|
|
header.Time = new(big.Int).Add(parent.Time, new(big.Int).SetUint64(a.config.Period))
|
|
|
|
|
if header.Time.Int64() < time.Now().Unix() {
|
|
|
|
|
header.Time = big.NewInt(time.Now().Unix())
|
|
|
|
|
}
|
|
|
|
|
@ -568,7 +555,7 @@ func (c *Aura) Prepare(chain consensus.ChainReader, header *types.Header) error
|
|
|
|
|
|
|
|
|
|
// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
|
|
|
|
|
// rewards given, and returns the final block.
|
|
|
|
|
func (c *Aura) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
|
|
|
|
func (a *Aura) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
|
|
|
|
// No block rewards in PoA, so the state remains as is and uncles are dropped
|
|
|
|
|
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
|
|
|
|
|
header.UncleHash = types.CalcUncleHash(nil)
|
|
|
|
|
@ -579,17 +566,17 @@ func (c *Aura) Finalize(chain consensus.ChainReader, header *types.Header, state
|
|
|
|
|
|
|
|
|
|
// Authorize injects a private key into the consensus engine to mint new blocks
|
|
|
|
|
// with.
|
|
|
|
|
func (c *Aura) Authorize(signer common.Address, signFn SignerFn) {
|
|
|
|
|
c.lock.Lock()
|
|
|
|
|
defer c.lock.Unlock()
|
|
|
|
|
func (a *Aura) Authorize(signer common.Address, signFn SignerFn) {
|
|
|
|
|
a.lock.Lock()
|
|
|
|
|
defer a.lock.Unlock()
|
|
|
|
|
|
|
|
|
|
c.signer = signer
|
|
|
|
|
c.signFn = signFn
|
|
|
|
|
a.signer = signer
|
|
|
|
|
a.signFn = signFn
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Seal implements consensus.Engine, attempting to create a sealed block using
|
|
|
|
|
// the local signing credentials.
|
|
|
|
|
func (c *Aura) Seal(chain consensus.ChainReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {
|
|
|
|
|
func (a *Aura) Seal(chain consensus.ChainReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {
|
|
|
|
|
header := block.Header()
|
|
|
|
|
|
|
|
|
|
// Sealing the genesis block is not supported
|
|
|
|
|
@ -598,16 +585,16 @@ func (c *Aura) Seal(chain consensus.ChainReader, block *types.Block, results cha
|
|
|
|
|
return errUnknownBlock
|
|
|
|
|
}
|
|
|
|
|
// For 0-period chains, refuse to seal empty blocks (no reward but would spin sealing)
|
|
|
|
|
if c.config.Period == 0 && len(block.Transactions()) == 0 {
|
|
|
|
|
if a.config.Period == 0 && len(block.Transactions()) == 0 {
|
|
|
|
|
return errWaitTransactions
|
|
|
|
|
}
|
|
|
|
|
// Don't hold the signer fields for the entire sealing procedure
|
|
|
|
|
c.lock.RLock()
|
|
|
|
|
signer, signFn := c.signer, c.signFn
|
|
|
|
|
c.lock.RUnlock()
|
|
|
|
|
a.lock.RLock()
|
|
|
|
|
signer, signFn := a.signer, a.signFn
|
|
|
|
|
a.lock.RUnlock()
|
|
|
|
|
|
|
|
|
|
// Bail out if we're unauthorized to sign a block
|
|
|
|
|
snap, err := c.snapshot(chain, number-1, header.ParentHash, nil)
|
|
|
|
|
snap, err := a.snapshot(chain, number-1, header.ParentHash, nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
@ -651,51 +638,35 @@ func (c *Aura) Seal(chain consensus.ChainReader, block *types.Block, results cha
|
|
|
|
|
select {
|
|
|
|
|
case results <- block.WithSeal(header):
|
|
|
|
|
default:
|
|
|
|
|
log.Warn("Sealing result is not read by miner", "sealhash", c.SealHash(header))
|
|
|
|
|
log.Warn("Sealing result is not read by miner", "sealhash", a.SealHash(header))
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
|
|
|
|
|
// that a new block should have based on the previous blocks in the chain and the
|
|
|
|
|
// current signer.
|
|
|
|
|
func (c *Aura) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
|
|
|
|
|
snap, err := c.snapshot(chain, parent.Number.Uint64(), parent.Hash(), nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
return CalcDifficulty(snap, c.signer)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
|
|
|
|
|
// that a new block should have based on the previous blocks in the chain and the
|
|
|
|
|
// current signer.
|
|
|
|
|
func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int {
|
|
|
|
|
if snap.inturn(snap.Number+1, signer) {
|
|
|
|
|
return new(big.Int).Set(diffInTurn)
|
|
|
|
|
}
|
|
|
|
|
return new(big.Int).Set(diffNoTurn)
|
|
|
|
|
// Returns difficulty constant from config
|
|
|
|
|
func (a *Aura) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
|
|
|
|
|
return new(big.Int).SetUint64(chain.Config().Aura.Difficulty)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SealHash returns the hash of a block prior to it being sealed.
|
|
|
|
|
func (c *Aura) SealHash(header *types.Header) common.Hash {
|
|
|
|
|
func (a *Aura) SealHash(header *types.Header) common.Hash {
|
|
|
|
|
return sigHash(header)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Close implements consensus.Engine. It's a noop for clique as there is are no background threads.
|
|
|
|
|
func (c *Aura) Close() error {
|
|
|
|
|
func (a *Aura) Close() error {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// APIs implements consensus.Engine, returning the user facing RPC API to allow
|
|
|
|
|
// controlling the signer voting.
|
|
|
|
|
func (c *Aura) APIs(chain consensus.ChainReader) []rpc.API {
|
|
|
|
|
func (a *Aura) APIs(chain consensus.ChainReader) []rpc.API {
|
|
|
|
|
return []rpc.API{{
|
|
|
|
|
Namespace: "clique",
|
|
|
|
|
Version: "1.0",
|
|
|
|
|
Service: &API{chain: chain, clique: c},
|
|
|
|
|
Service: &API{chain: chain, aura: a},
|
|
|
|
|
Public: false,
|
|
|
|
|
}}
|
|
|
|
|
}
|