fix panic by parlia consensus (#5078)

This commit is contained in:
fynn.z 2022-08-16 20:16:16 +08:00 committed by GitHub
parent 5c05ebcbeb
commit 597d1e5a64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 22 deletions

View File

@ -2,9 +2,11 @@ package parlia
import (
"bytes"
"context"
"encoding/hex"
"errors"
"fmt"
"github.com/ledgerwatch/erigon/core/rawdb"
"io"
"math/big"
"sort"
@ -218,6 +220,7 @@ type Parlia struct {
config *params.ParliaConfig // Consensus engine configuration parameters for parlia consensus
genesisHash common.Hash
db kv.RwDB // Database to store and retrieve snapshot checkpoints
chainDb kv.RwDB
recentSnaps *lru.ARCCache // Snapshots for recent block to speed up
signatures *lru.ARCCache // Signatures of recent blocks to speed up mining
@ -243,6 +246,7 @@ func New(
chainConfig *params.ChainConfig,
db kv.RwDB,
snapshots *snapshotsync.RoSnapshots,
chainDb kv.RwDB,
) *Parlia {
// get parlia config
parliaConfig := chainConfig.Parlia
@ -273,6 +277,7 @@ func New(
chainConfig: chainConfig,
config: parliaConfig,
db: db,
chainDb: chainDb,
recentSnaps: recentSnaps,
signatures: signatures,
validatorSetABI: vABI,
@ -839,27 +844,29 @@ func (p *Parlia) Seal(chain consensus.ChainHeaderReader, block *types.Block, res
// Wait until sealing is terminated or delay timeout.
//log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay))
select {
case <-stop:
return nil
case <-time.After(delay):
}
if p.shouldWaitForCurrentBlockProcess(chain, header, snap) {
log.Info("[parlia] Waiting for received in turn block to process")
go func() {
select {
case <-stop:
log.Info("[parlia] Received block process finished, abort block seal")
return nil
case <-time.After(time.Duration(processBackOffTime) * time.Second):
log.Info("[parlia] Process backoff time exhausted, start to seal block")
return
case <-time.After(delay):
}
if p.shouldWaitForCurrentBlockProcess(p.chainDb, header, snap) {
log.Info("[parlia] Waiting for received in turn block to process")
select {
case <-stop:
log.Info("[parlia] Received block process finished, abort block seal")
return
case <-time.After(time.Duration(processBackOffTime) * time.Second):
log.Info("[parlia] Process backoff time exhausted, start to seal block")
}
}
}
select {
case results <- block.WithSeal(header):
default:
log.Warn("[parlia] Sealing result is not read by miner", "sealhash", SealHash(header, p.chainConfig.ChainID))
}
select {
case results <- block.WithSeal(header):
default:
log.Warn("[parlia] Sealing result is not read by miner", "sealhash", SealHash(header, p.chainConfig.ChainID))
}
}()
return nil
}
@ -930,12 +937,20 @@ func (p *Parlia) IsSystemContract(to *common.Address) bool {
return isToSystemContract(*to)
}
func (p *Parlia) shouldWaitForCurrentBlockProcess(chain consensus.ChainHeaderReader, header *types.Header, snap *Snapshot) bool {
func (p *Parlia) shouldWaitForCurrentBlockProcess(chainDb kv.RwDB, header *types.Header, snap *Snapshot) bool {
if header.Difficulty.Cmp(diffInTurn) == 0 {
return false
}
highestVerifiedHeader := chain.CurrentHeader()
roTx, err := chainDb.BeginRo(context.Background())
if err != nil {
return false
}
defer roTx.Rollback()
hash := rawdb.ReadHeadHeaderHash(roTx)
number := rawdb.ReadHeaderNumber(roTx, hash)
highestVerifiedHeader := rawdb.ReadHeader(roTx, hash, *number)
if highestVerifiedHeader == nil {
return false
}

View File

@ -345,7 +345,7 @@ func New(stack *node.Node, config *ethconfig.Config, logger log.Logger) (*Ethere
} else {
consensusConfig = &config.Ethash
}
backend.engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, consensusConfig, config.Miner.Notify, config.Miner.Noverify, config.HeimdallURL, config.WithoutHeimdall, stack.DataDir(), allSnapshots, false /* readonly */)
backend.engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, consensusConfig, config.Miner.Notify, config.Miner.Noverify, config.HeimdallURL, config.WithoutHeimdall, stack.DataDir(), allSnapshots, false /* readonly */, backend.chainDB)
backend.forkValidator = engineapi.NewForkValidator(currentBlockNumber, inMemoryExecution)
backend.sentriesClient, err = sentry.NewMultiClient(

View File

@ -1,6 +1,7 @@
package ethconsensusconfig
import (
"github.com/ledgerwatch/erigon-lib/kv"
"path/filepath"
"github.com/davecgh/go-spew/spew"
@ -18,7 +19,7 @@ import (
"github.com/ledgerwatch/log/v3"
)
func CreateConsensusEngine(chainConfig *params.ChainConfig, logger log.Logger, config interface{}, notify []string, noverify bool, HeimdallURL string, WithoutHeimdall bool, datadir string, snapshots *snapshotsync.RoSnapshots, readonly bool) consensus.Engine {
func CreateConsensusEngine(chainConfig *params.ChainConfig, logger log.Logger, config interface{}, notify []string, noverify bool, HeimdallURL string, WithoutHeimdall bool, datadir string, snapshots *snapshotsync.RoSnapshots, readonly bool, chainDb ...kv.RwDB) consensus.Engine {
var eng consensus.Engine
switch consensusCfg := config.(type) {
@ -57,7 +58,7 @@ func CreateConsensusEngine(chainConfig *params.ChainConfig, logger log.Logger, c
}
case *params.ParliaConfig:
if chainConfig.Parlia != nil {
eng = parlia.New(chainConfig, db.OpenDatabase(consensusCfg.DBPath, logger, consensusCfg.InMemory, readonly), snapshots)
eng = parlia.New(chainConfig, db.OpenDatabase(consensusCfg.DBPath, logger, consensusCfg.InMemory, readonly), snapshots, chainDb[0])
}
case *params.BorConfig:
if chainConfig.Bor != nil {