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).
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")
// 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.
errInvalidVotingChain = errors.New("invalid voting chain")
// errUnauthorized is returned if a header is signed by a non-authorized entity.
errUnauthorized = errors.New("unauthorized")
// errUnauthorizedSigner is returned if a header is signed by a non-authorized entity.
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")
// 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")
)
@ -431,7 +435,7 @@ func (c *XDPoS) verifyCascadingFields(chain consensus.ChainReader, header *types
validSigners := compareSignersLists(masternodesFromCheckpointHeader, signers)
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)
return errInvalidCheckpointSigners
return errMismatchingCheckpointSigners
}
if c.HookVerifyMNs != nil {
err := c.HookVerifyMNs(header, signers)
@ -702,7 +706,7 @@ func (c *XDPoS) verifySeal(chain consensus.ChainReader, header *types.Header, pa
}
if !valid {
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 {
@ -713,7 +717,7 @@ func (c *XDPoS) verifySeal(chain consensus.ChainReader, header *types.Header, pa
if limit := uint64(2); seen > number-limit {
// Only take into account the non-epoch blocks
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)
// checkpoint blocks have no tx
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
c.lock.RLock()
@ -965,7 +970,7 @@ func (c *XDPoS) Seal(chain consensus.ChainReader, block *types.Block, results ch
}
}
if !valid {
return errUnauthorized
return errUnauthorizedSigner
}
}
// 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/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
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.
type Snapshot struct {
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
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 {
// return nil, errUnauthorizedSigner
//}
//for _, recent := range snap.Recents {
// if recent == signer {
// return nil, errRecentlySigned
// }
//}
for seen, recent := range snap.Recents {
if recent == signer {
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
// 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))
// Import all the pruned blocks to make the state available
_, _, _, err := bc.insertChain(winner, false)
if err != nil {
return nil, err
if len(winner) > 0 {
_, _, _, err := bc.insertChain(winner, false)
if err != nil {
return nil, err
}
}
case err != nil:
bc.reportBlock(block, nil, err)

View file

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