diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index defc62f0cf..b7be559c95 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -53,7 +53,7 @@ const ( inMemoryHeaders = 86400 // Number of recent headers to keep in memory for double sign detection, checkpointInterval = 1024 // Number of blocks after which to save the snapshot to the database - defaultEpochLength = uint64(100) // Default number of blocks of checkpoint to update validatorSet from contract + defaultEpochLength = uint64(200) // Default number of blocks of checkpoint to update validatorSet from contract 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 @@ -713,13 +713,26 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash } } - // If we're at the genesis, snapshot the initial state. - if number == 0 { - checkpoint := chain.GetHeaderByNumber(number) - if checkpoint != nil { - // get checkpoint data - hash := checkpoint.Hash() - + // If we're at the genesis, snapshot the initial state. Alternatively if we have + // piled up more headers than allowed to be reorged (chain reinit from a freezer), + // consider the checkpoint trusted and snapshot it. + // even BEP-341 enabled, an offset `defaultEpochLength/2` can ensure getting the right validators. + if number == 0 || (number%p.config.Epoch == defaultEpochLength/2 && (len(headers) > int(params.FullImmutabilityThreshold)/10)) { + var ( + checkpoint *types.Header + blockHash common.Hash + ) + if number == 0 { + checkpoint := chain.GetHeaderByNumber(0) + blockHash = checkpoint.Hash() + } else { + checkpoint = chain.GetHeaderByNumber(number - defaultEpochLength/2) + blockHeader := chain.GetHeaderByNumber(number) + if blockHeader != nil { + blockHash = blockHeader.Hash() + } + } + if checkpoint != nil && blockHash != (common.Hash{}) { // get validators from headers validators, voteAddrs, err := parseValidators(checkpoint, p.chainConfig, p.config) if err != nil { @@ -727,11 +740,11 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash } // new snapshot - snap = newSnapshot(p.config, p.signatures, number, hash, validators, voteAddrs, p.ethAPI) + snap = newSnapshot(p.config, p.signatures, number, blockHash, validators, voteAddrs, p.ethAPI) if err := snap.store(p.db); err != nil { return nil, err } - log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash) + log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", blockHash) break } }