mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
fix masternode stop block production.
This commit is contained in:
parent
a8fc240b29
commit
916b16de71
4 changed files with 42 additions and 33 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in a new issue