fix masternode stop block production.

This commit is contained in:
AnilChinchawale 2021-01-18 10:57:22 +05:30
parent a8fc240b29
commit 916b16de71
4 changed files with 42 additions and 33 deletions

View file

@ -114,6 +114,11 @@ var (
// ones). // ones).
errInvalidCheckpointSigners = errors.New("invalid signer list on checkpoint block") errInvalidCheckpointSigners = errors.New("invalid signer list on checkpoint block")
// errMismatchingCheckpointSigners is returned if a checkpoint block contains a
// list of signers different than the one the local node calculated.
errMismatchingCheckpointSigners = errors.New("mismatching signer list on checkpoint block")
errInvalidCheckpointPenalties = errors.New("invalid penalty list on checkpoint block") errInvalidCheckpointPenalties = errors.New("invalid penalty 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.
@ -134,16 +139,15 @@ var (
// be modified via out-of-range or non-contiguous headers. // be modified via out-of-range or non-contiguous headers.
errInvalidVotingChain = errors.New("invalid voting chain") errInvalidVotingChain = errors.New("invalid voting chain")
// errUnauthorized is returned if a header is signed by a non-authorized entity. // errUnauthorizedSigner is returned if a header is signed by a non-authorized entity.
errUnauthorized = errors.New("unauthorized") errUnauthorizedSigner = errors.New("unauthorized signer")
// errRecentlySigned is returned if a header is signed by an authorized entity
// that already signed a header recently, thus is temporarily not allowed to.
errRecentlySigned = errors.New("recently signed")
errFailedDoubleValidation = errors.New("wrong pair of creator-validator in double validation") errFailedDoubleValidation = errors.New("wrong pair of creator-validator in double validation")
// errWaitTransactions is returned if an empty block is attempted to be sealed
// on an instant chain (0 second period). It's important to refuse these as the
// block reward is zero, so an empty block just bloats the chain... fast.
errWaitTransactions = errors.New("waiting for transactions")
ErrInvalidCheckpointValidators = errors.New("invalid validators list on checkpoint block") ErrInvalidCheckpointValidators = errors.New("invalid validators list on checkpoint block")
) )
@ -431,7 +435,7 @@ func (c *XDPoS) verifyCascadingFields(chain consensus.ChainReader, header *types
validSigners := compareSignersLists(masternodesFromCheckpointHeader, signers) validSigners := compareSignersLists(masternodesFromCheckpointHeader, signers)
if !validSigners { if !validSigners {
log.Error("Masternodes lists are different in checkpoint header and snapshot", "number", number, "masternodes_from_checkpoint_header", masternodesFromCheckpointHeader, "masternodes_in_snapshot", signers, "penList", penPenalties) log.Error("Masternodes lists are different in checkpoint header and snapshot", "number", number, "masternodes_from_checkpoint_header", masternodesFromCheckpointHeader, "masternodes_in_snapshot", signers, "penList", penPenalties)
return errInvalidCheckpointSigners return errMismatchingCheckpointSigners
} }
if c.HookVerifyMNs != nil { if c.HookVerifyMNs != nil {
err := c.HookVerifyMNs(header, signers) err := c.HookVerifyMNs(header, signers)
@ -702,7 +706,7 @@ func (c *XDPoS) verifySeal(chain consensus.ChainReader, header *types.Header, pa
} }
if !valid { if !valid {
log.Debug("Unauthorized creator found", "block number", number, "creator", creator.String(), "masternodes", mstring, "snapshot from parent block", nstring) log.Debug("Unauthorized creator found", "block number", number, "creator", creator.String(), "masternodes", mstring, "snapshot from parent block", nstring)
return errUnauthorized return errUnauthorizedSigner
} }
} }
if len(masternodes) > 1 { if len(masternodes) > 1 {
@ -713,7 +717,7 @@ func (c *XDPoS) verifySeal(chain consensus.ChainReader, header *types.Header, pa
if limit := uint64(2); seen > number-limit { if limit := uint64(2); seen > number-limit {
// Only take into account the non-epoch blocks // Only take into account the non-epoch blocks
if number%c.config.Epoch != 0 { if number%c.config.Epoch != 0 {
return errUnauthorized return errRecentlySigned
} }
} }
} }
@ -943,7 +947,8 @@ func (c *XDPoS) Seal(chain consensus.ChainReader, block *types.Block, results ch
// For 0-period chains, refuse to seal empty blocks (no reward but would spin sealing) // For 0-period chains, refuse to seal empty blocks (no reward but would spin sealing)
// checkpoint blocks have no tx // checkpoint blocks have no tx
if c.config.Period == 0 && len(block.Transactions()) == 0 && number%c.config.Epoch != 0 { if c.config.Period == 0 && len(block.Transactions()) == 0 && number%c.config.Epoch != 0 {
return errWaitTransactions log.Info("Sealing paused, waiting for transactions")
return nil
} }
// Don't hold the signer fields for the entire sealing procedure // Don't hold the signer fields for the entire sealing procedure
c.lock.RLock() c.lock.RLock()
@ -965,7 +970,7 @@ func (c *XDPoS) Seal(chain consensus.ChainReader, block *types.Block, results ch
} }
} }
if !valid { if !valid {
return errUnauthorized return errUnauthorizedSigner
} }
} }
// If we're amongst the recent signers, wait for the next block // If we're amongst the recent signers, wait for the next block

View file

@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/consensus/clique"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
lru "github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
) )
@ -47,7 +48,7 @@ import (
// Snapshot is the state of the authorization voting at a given point in time. // Snapshot is the state of the authorization voting at a given point in time.
type Snapshot struct { type Snapshot struct {
config *params.XDPoSConfig // Consensus engine parameters to fine tune behavior config *params.XDPoSConfig // Consensus engine parameters to fine tune behavior
sigcache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover sigcache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover
Number uint64 `json:"number"` // Block number where the snapshot was created Number uint64 `json:"number"` // Block number where the snapshot was created
Hash common.Hash `json:"hash"` // Block hash where the snapshot was created Hash common.Hash `json:"hash"` // Block hash where the snapshot was created
@ -217,11 +218,16 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
//if _, ok := snap.Signers[signer]; !ok { //if _, ok := snap.Signers[signer]; !ok {
// return nil, errUnauthorizedSigner // return nil, errUnauthorizedSigner
//} //}
//for _, recent := range snap.Recents { for seen, recent := range snap.Recents {
// if recent == signer { if recent == signer {
// return nil, errRecentlySigned if limit := uint64(2); number < limit || seen > number-limit {
// } if number%s.config.Epoch != 0 {
//} log.Error("errRecentlySigned")
return nil, errRecentlySigned
}
}
}
}
snap.Recents[number] = signer snap.Recents[number] = signer
// Header authorized, discard any previous votes from the signer // Header authorized, discard any previous votes from the signer

View file

@ -1406,9 +1406,11 @@ func (bc *BlockChain) getResultBlock(block *types.Block, verifiedM2 bool) (*Resu
} }
log.Debug("Number block need calculated again", "number", block.NumberU64(), "hash", block.Hash().Hex(), "winners", len(winner)) log.Debug("Number block need calculated again", "number", block.NumberU64(), "hash", block.Hash().Hex(), "winners", len(winner))
// Import all the pruned blocks to make the state available // Import all the pruned blocks to make the state available
_, _, _, err := bc.insertChain(winner, false) if len(winner) > 0 {
if err != nil { _, _, _, err := bc.insertChain(winner, false)
return nil, err if err != nil {
return nil, err
}
} }
case err != nil: case err != nil:
bc.reportBlock(block, nil, err) bc.reportBlock(block, nil, err)

View file

@ -29,8 +29,8 @@ import (
mapset "github.com/deckarep/golang-set" mapset "github.com/deckarep/golang-set"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/consensus/XDPoS" "github.com/ethereum/go-ethereum/consensus/XDPoS"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/contracts" "github.com/ethereum/go-ethereum/contracts"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
@ -174,8 +174,8 @@ type worker struct {
snapshotState *state.StateDB snapshotState *state.StateDB
// atomic status counters // atomic status counters
running int32 // The indicator whether the consensus engine is running or not. running int32 // The indicator whether the consensus engine is running or not.
newTxs int32 // New arrival transaction count since last sealing work submitting. newTxs int32 // New arrival transaction count since last sealing work submitting.
announceTxs bool announceTxs bool
lastParentBlockCommit string lastParentBlockCommit string
@ -213,7 +213,7 @@ func newWorker(config *params.ChainConfig, engine consensus.Engine, eth Backend,
startCh: make(chan struct{}, 1), startCh: make(chan struct{}, 1),
resubmitIntervalCh: make(chan time.Duration), resubmitIntervalCh: make(chan time.Duration),
resubmitAdjustCh: make(chan *intervalAdjust, resubmitAdjustChanSize), resubmitAdjustCh: make(chan *intervalAdjust, resubmitAdjustChanSize),
announceTxs: announceTxs, announceTxs: announceTxs,
} }
if worker.announceTxs { if worker.announceTxs {
// Subscribe NewTxsEvent for tx pool // Subscribe NewTxsEvent for tx pool
@ -374,13 +374,8 @@ func (w *worker) newWorkLoop(recommit time.Duration) {
case <-timer.C: case <-timer.C:
// If mining is running resubmit a new work cycle periodically to pull in // If mining is running resubmit a new work cycle periodically to pull in
// higher priced transactions. Disable this overhead for pending blocks. // higher priced transactions. Disable this overhead for pending blocks.
if w.isRunning() && (w.config.Clique == nil || w.config.Clique.Period > 0) { if w.isRunning() && (w.config.XDPoS == nil || w.config.XDPoS.Period > 0) {
// Short circuit if no new transaction arrives. commit(false, commitInterruptResubmit)
if atomic.LoadInt32(&w.newTxs) == 0 {
timer.Reset(recommit)
continue
}
commit(true, commitInterruptResubmit)
} }
case interval := <-w.resubmitIntervalCh: case interval := <-w.resubmitIntervalCh:
@ -984,7 +979,7 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64)
return return
} }
if !ok { if !ok {
log.Info("Not my turn to commit block. Waiting...") log.Info("Not my turn to commit block. Waiting...", "coinbase", w.coinbase, "parent", parent.Header().Number)
// in case some nodes are down // in case some nodes are down
if preIndex == -1 { if preIndex == -1 {
// first block // first block
@ -1150,6 +1145,7 @@ func (w *worker) commit(uncles []*types.Header, interval func(), update bool, st
receipts[i] = new(types.Receipt) receipts[i] = new(types.Receipt)
*receipts[i] = *l *receipts[i] = *l
} }
log.Info("commit", "root", w.current.state.IntermediateRoot(true).String())
s := w.current.state.Copy() s := w.current.state.Copy()
block, err := w.engine.Finalize(w.chain, w.current.header, s, w.current.txs, uncles, w.current.receipts) block, err := w.engine.Finalize(w.chain, w.current.header, s, w.current.txs, uncles, w.current.receipts)
if err != nil { if err != nil {