diff --git a/cmd/integration/commands/stages.go b/cmd/integration/commands/stages.go index d40352406cf..5b7fb5e9081 100644 --- a/cmd/integration/commands/stages.go +++ b/cmd/integration/commands/stages.go @@ -1149,24 +1149,7 @@ func newSync(ctx context.Context, db kv.RwDB, miningConfig *params.MiningConfig) } vmConfig := &vm.Config{} - genesis, chainConfig := byChain(chain) - var engine consensus.Engine - config := ðconfig.Defaults - if chainConfig.Clique != nil { - c := params.CliqueSnapshot - c.DBPath = filepath.Join(datadir, "clique", "db") - engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, c, config.Miner.Notify, config.Miner.Noverify, "", true, datadir) - } else if chainConfig.Aura != nil { - engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, ¶ms.AuRaConfig{DBPath: filepath.Join(datadir, "aura")}, config.Miner.Notify, config.Miner.Noverify, "", true, datadir) - } else if chainConfig.Parlia != nil { - consensusConfig := ¶ms.ParliaConfig{DBPath: filepath.Join(datadir, "parlia")} - engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, consensusConfig, config.Miner.Notify, config.Miner.Noverify, "", true, datadir) - } else if chainConfig.Bor != nil { - consensusConfig := &config.Bor - engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, consensusConfig, config.Miner.Notify, config.Miner.Noverify, HeimdallURL, false, datadir) - } else { //ethash - engine = ethash.NewFaker() - } + genesis, _ := byChain(chain) events := privateapi.NewEvents() @@ -1184,13 +1167,6 @@ func newSync(ctx context.Context, db kv.RwDB, miningConfig *params.MiningConfig) var batchSize datasize.ByteSize must(batchSize.UnmarshalText([]byte(batchSizeStr))) - br := getBlockReader(chainConfig) - blockDownloaderWindow := 65536 - sentryControlServer, err := sentry.NewControlServer(db, "", chainConfig, genesisBlock.Hash(), engine, 1, nil, blockDownloaderWindow, br) - if err != nil { - panic(err) - } - cfg := ethconfig.Defaults cfg.Prune = pm cfg.BatchSize = batchSize @@ -1206,6 +1182,30 @@ func newSync(ctx context.Context, db kv.RwDB, miningConfig *params.MiningConfig) snDir := &dir.Rw{Path: filepath.Join(datadir, "snapshots")} cfg.SnapshotDir = snDir } + var engine consensus.Engine + config := ðconfig.Defaults + if chainConfig.Clique != nil { + c := params.CliqueSnapshot + c.DBPath = filepath.Join(datadir, "clique", "db") + engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, c, config.Miner.Notify, config.Miner.Noverify, "", true, datadir, allSn) + } else if chainConfig.Aura != nil { + engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, ¶ms.AuRaConfig{DBPath: filepath.Join(datadir, "aura")}, config.Miner.Notify, config.Miner.Noverify, "", true, datadir, allSn) + } else if chainConfig.Parlia != nil { + consensusConfig := ¶ms.ParliaConfig{DBPath: filepath.Join(datadir, "parlia")} + engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, consensusConfig, config.Miner.Notify, config.Miner.Noverify, "", true, datadir, allSn) + } else if chainConfig.Bor != nil { + consensusConfig := &config.Bor + engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, consensusConfig, config.Miner.Notify, config.Miner.Noverify, HeimdallURL, false, datadir, allSn) + } else { //ethash + engine = ethash.NewFaker() + } + + br := getBlockReader(chainConfig) + blockDownloaderWindow := 65536 + sentryControlServer, err := sentry.NewControlServer(db, "", chainConfig, genesisBlock.Hash(), engine, 1, nil, blockDownloaderWindow, br) + if err != nil { + panic(err) + } sync, err := stages2.NewStagedSync(context.Background(), logger, db, p2p.Config{}, cfg, chainConfig.TerminalTotalDifficulty, sentryControlServer, tmpdir, diff --git a/cmd/state/commands/erigon2.go b/cmd/state/commands/erigon2.go index 610ca52f677..6526c342776 100644 --- a/cmd/state/commands/erigon2.go +++ b/cmd/state/commands/erigon2.go @@ -205,16 +205,17 @@ func Erigon2(genesis *core.Genesis, chainConfig *params.ChainConfig, logger log. } }() - engine := initConsensusEngine(chainConfig, logger) var blockReader interfaces.FullBlockReader + var allSnapshots *snapshotsync.RoSnapshots syncMode := ethconfig.SyncModeByChainName(chainConfig.ChainName, syncmodeCli) if syncMode == ethconfig.SnapSync { - allSnapshots := snapshotsync.NewRoSnapshots(ethconfig.NewSnapshotCfg(true, false), path.Join(datadir, "snapshots")) + allSnapshots = snapshotsync.NewRoSnapshots(ethconfig.NewSnapshotCfg(true, false), path.Join(datadir, "snapshots")) defer allSnapshots.Close() blockReader = snapshotsync.NewBlockReaderWithSnapshots(allSnapshots) } else { blockReader = snapshotsync.NewBlockReader() } + engine := initConsensusEngine(chainConfig, logger, allSnapshots) for !interrupt { blockNum++ @@ -598,23 +599,23 @@ func (ww *WriterWrapper) CreateContract(address common.Address) error { return nil } -func initConsensusEngine(chainConfig *params.ChainConfig, logger log.Logger) (engine consensus.Engine) { +func initConsensusEngine(chainConfig *params.ChainConfig, logger log.Logger, snapshots *snapshotsync.RoSnapshots) (engine consensus.Engine) { config := ethconfig.Defaults switch { case chainConfig.Clique != nil: c := params.CliqueSnapshot c.DBPath = filepath.Join(datadir, "clique", "db") - engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, c, config.Miner.Notify, config.Miner.Noverify, "", true, datadir) + engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, c, config.Miner.Notify, config.Miner.Noverify, "", true, datadir, snapshots) case chainConfig.Aura != nil: consensusConfig := ¶ms.AuRaConfig{DBPath: filepath.Join(datadir, "aura")} - engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, consensusConfig, config.Miner.Notify, config.Miner.Noverify, "", true, datadir) + engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, consensusConfig, config.Miner.Notify, config.Miner.Noverify, "", true, datadir, snapshots) case chainConfig.Parlia != nil: consensusConfig := ¶ms.ParliaConfig{DBPath: filepath.Join(datadir, "parlia")} - engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, consensusConfig, config.Miner.Notify, config.Miner.Noverify, "", true, datadir) + engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, consensusConfig, config.Miner.Notify, config.Miner.Noverify, "", true, datadir, snapshots) case chainConfig.Bor != nil: consensusConfig := &config.Bor - engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, consensusConfig, config.Miner.Notify, config.Miner.Noverify, "http://localhost:1317", false, datadir) + engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, consensusConfig, config.Miner.Notify, config.Miner.Noverify, "http://localhost:1317", false, datadir, snapshots) default: //ethash engine = ethash.NewFaker() } diff --git a/consensus/parlia/api.go b/consensus/parlia/api.go index 05aaeefed70..fbcec09e6e6 100644 --- a/consensus/parlia/api.go +++ b/consensus/parlia/api.go @@ -42,7 +42,7 @@ func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) { if header == nil { return nil, errUnknownBlock } - return api.parlia.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) + return api.parlia.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil, false /* verify */) } // GetSnapshotAtHash retrieves the state snapshot at a given block. @@ -51,7 +51,7 @@ func (api *API) GetSnapshotAtHash(hash common.Hash) (*Snapshot, error) { if header == nil { return nil, errUnknownBlock } - return api.parlia.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) + return api.parlia.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil, false /* verify */) } // GetValidators retrieves the list of validators at the specified block. @@ -67,7 +67,7 @@ func (api *API) GetValidators(number *rpc.BlockNumber) ([]common.Address, error) if header == nil { return nil, errUnknownBlock } - snap, err := api.parlia.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) + snap, err := api.parlia.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil, false /* verify */) if err != nil { return nil, err } @@ -80,7 +80,7 @@ func (api *API) GetValidatorsAtHash(hash common.Hash) ([]common.Address, error) if header == nil { return nil, errUnknownBlock } - snap, err := api.parlia.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) + snap, err := api.parlia.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil, false /* verify */) if err != nil { return nil, err } diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 89052cdf821..d1ca6701cca 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -36,6 +36,7 @@ import ( "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/erigon/rpc" + "github.com/ledgerwatch/erigon/turbo/snapshotsync" ) const ( @@ -232,14 +233,16 @@ type Parlia struct { slashABI abi.ABI // The fields below are for testing only - fakeDiff bool // Skip difficulty verifications - forks []uint64 // Forks extracted from the chainConfig + fakeDiff bool // Skip difficulty verifications + forks []uint64 // Forks extracted from the chainConfig + snapshots *snapshotsync.RoSnapshots } // New creates a Parlia consensus engine. func New( chainConfig *params.ChainConfig, db kv.RwDB, + snapshots *snapshotsync.RoSnapshots, ) *Parlia { // get parlia config parliaConfig := chainConfig.Parlia @@ -276,6 +279,7 @@ func New( slashABI: sABI, signer: types.LatestSigner(chainConfig), forks: forkid.GatherForks(chainConfig), + snapshots: snapshots, } return c @@ -392,7 +396,7 @@ func (p *Parlia) verifyCascadingFields(chain consensus.ChainHeaderReader, header return consensus.ErrUnknownAncestor } - snap, err := p.snapshot(chain, number-1, header.ParentHash, parents) + snap, err := p.snapshot(chain, number-1, header.ParentHash, parents, true /* verify */) if err != nil { return err } @@ -438,7 +442,7 @@ func (p *Parlia) verifySeal(chain consensus.ChainHeaderReader, header *types.Hea return errUnknownBlock } // Retrieve the snapshot needed to verify this header and cache it - snap, err := p.snapshot(chain, number-1, header.ParentHash, parents) + snap, err := p.snapshot(chain, number-1, header.ParentHash, parents, true /* verify */) if err != nil { return err } @@ -481,7 +485,7 @@ func (p *Parlia) verifySeal(chain consensus.ChainHeaderReader, header *types.Hea } // snapshot retrieves the authorization snapshot at a given point in time. -func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) { +func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash common.Hash, parents []*types.Header, verify bool) (*Snapshot, error) { // Search for a snapshot in memory or on disk for checkpoints var ( headers []*types.Header @@ -500,31 +504,26 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash if s, err := loadSnapshot(p.config, p.signatures, p.db, number, hash); err == nil { log.Trace("Loaded snapshot from disk", "number", number, "hash", hash) snap = s - break + if !verify || snap != nil { + break + } } } - - // 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() - - validatorBytes := checkpoint.Extra[extraVanity : len(checkpoint.Extra)-extraSeal] - // get validators from headers - validators, err := ParseValidators(validatorBytes) - if err != nil { - return nil, err + if (verify && number%p.config.Epoch == 0) || number == 0 { + if (p.snapshots != nil && number <= p.snapshots.BlocksAvailable()) || number == 0 { + // Headers included into the snapshots have to be trusted as checkpoints + checkpoint := chain.GetHeader(hash, number) + if checkpoint != nil { + validatorBytes := checkpoint.Extra[extraVanity : len(checkpoint.Extra)-extraSeal] + // get validators from headers + validators, err := ParseValidators(validatorBytes) + if err != nil { + return nil, err + } + // new snapshot + snap = newSnapshot(p.config, p.signatures, number, hash, validators) + break } - - // new snapshot - snap = newSnapshot(p.config, p.signatures, number, hash, validators) - if err := snap.store(p.db); err != nil { - return nil, err - } - log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash) - break } } @@ -557,7 +556,6 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash for i := 0; i < len(headers)/2; i++ { headers[i], headers[len(headers)-1-i] = headers[len(headers)-1-i], headers[i] } - snap, err := snap.apply(headers, chain, parents, p.chainConfig.ChainID) if err != nil { return nil, err @@ -590,7 +588,7 @@ func (p *Parlia) Prepare(chain consensus.ChainHeaderReader, header *types.Header header.Nonce = types.BlockNonce{} number := header.Number.Uint64() - snap, err := p.snapshot(chain, number-1, header.ParentHash, nil) + snap, err := p.snapshot(chain, number-1, header.ParentHash, nil, false /* verify */) if err != nil { return err } @@ -685,7 +683,7 @@ func (p *Parlia) finalize(header *types.Header, state *state.IntraBlockState, tx txs = userTxs // warn if not in majority fork number := header.Number.Uint64() - snap, err := p.snapshot(chain, number-1, header.ParentHash, nil) + snap, err := p.snapshot(chain, number-1, header.ParentHash, nil, false /* verify */) if err != nil { return nil, nil, err } @@ -805,7 +803,7 @@ func (p *Parlia) Seal(chain consensus.ChainHeaderReader, block *types.Block, res val, signFn := p.val, p.signFn p.lock.RUnlock() - snap, err := p.snapshot(chain, number-1, header.ParentHash, nil) + snap, err := p.snapshot(chain, number-1, header.ParentHash, nil, false /* verify */) if err != nil { return err } @@ -875,7 +873,7 @@ func (p *Parlia) SealHash(header *types.Header) common.Hash { // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty // that a new block should have. func (p *Parlia) CalcDifficulty(chain consensus.ChainHeaderReader, time, parentTime uint64, parentDifficulty *big.Int, parentNumber uint64, parentHash, parentUncleHash common.Hash, parentSeal []rlp.RawValue) *big.Int { - snap, err := p.snapshot(chain, parentNumber, parentHash, nil) + snap, err := p.snapshot(chain, parentNumber, parentHash, nil, false /* verify */) if err != nil { return nil } @@ -950,7 +948,7 @@ func (p *Parlia) shouldWaitForCurrentBlockProcess(chain consensus.ChainHeaderRea } func (p *Parlia) EnoughDistance(chain consensus.ChainReader, header *types.Header) bool { - snap, err := p.snapshot(chain, header.Number.Uint64()-1, header.ParentHash, nil) + snap, err := p.snapshot(chain, header.Number.Uint64()-1, header.ParentHash, nil, false /* verify */) if err != nil { return true } @@ -962,7 +960,7 @@ func (p *Parlia) IsLocalBlock(header *types.Header) bool { } func (p *Parlia) AllowLightProcess(chain consensus.ChainReader, currentHeader *types.Header) bool { - snap, err := p.snapshot(chain, currentHeader.Number.Uint64()-1, currentHeader.ParentHash, nil) + snap, err := p.snapshot(chain, currentHeader.Number.Uint64()-1, currentHeader.ParentHash, nil, false /* verify */) if err != nil { return true } diff --git a/eth/backend.go b/eth/backend.go index da5a1fd4f7f..3de4032cf5a 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -218,44 +218,6 @@ func New(stack *node.Node, config *ethconfig.Config, txpoolCfg txpool2.Config, l } backend.gasPrice, _ = uint256.FromBig(config.Miner.GasPrice) - var consensusConfig interface{} - - if chainConfig.Clique != nil { - consensusConfig = &config.Clique - } else if chainConfig.Aura != nil { - config.Aura.Etherbase = config.Miner.Etherbase - consensusConfig = &config.Aura - } else if chainConfig.Parlia != nil { - consensusConfig = &config.Parlia - } else if chainConfig.Bor != nil { - consensusConfig = &config.Bor - } else { - consensusConfig = &config.Ethash - } - - backend.engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, consensusConfig, config.Miner.Notify, config.Miner.Noverify, config.HeimdallURL, config.WithoutHeimdall, stack.DataDir()) - - log.Info("Initialising Ethereum protocol", "network", config.NetworkID) - - if err := chainKv.Update(context.Background(), func(tx kv.RwTx) error { - if err = stagedsync.UpdateMetrics(tx); err != nil { - return err - } - - config.Prune, err = prune.EnsureNotChanged(tx, config.Prune) - if err != nil { - return err - } - if err := snap.EnsureNotChanged(tx, config.Snapshot); err != nil { - return err - } - log.Info("Effective", "prune_flags", config.Prune.String(), "snapshot_flags", config.Snapshot.String()) - - return nil - }); err != nil { - return nil, err - } - if config.TxPool.Journal != "" { config.TxPool.Journal = stack.ResolvePath(config.TxPool.Journal) } @@ -344,6 +306,44 @@ func New(stack *node.Node, config *ethconfig.Config, txpoolCfg txpool2.Config, l blockReader = snapshotsync.NewBlockReader() } + var consensusConfig interface{} + + if chainConfig.Clique != nil { + consensusConfig = &config.Clique + } else if chainConfig.Aura != nil { + config.Aura.Etherbase = config.Miner.Etherbase + consensusConfig = &config.Aura + } else if chainConfig.Parlia != nil { + consensusConfig = &config.Parlia + } else if chainConfig.Bor != nil { + consensusConfig = &config.Bor + } else { + consensusConfig = &config.Ethash + } + + backend.engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, consensusConfig, config.Miner.Notify, config.Miner.Noverify, config.HeimdallURL, config.WithoutHeimdall, stack.DataDir(), allSnapshots) + + log.Info("Initialising Ethereum protocol", "network", config.NetworkID) + + if err := chainKv.Update(context.Background(), func(tx kv.RwTx) error { + if err = stagedsync.UpdateMetrics(tx); err != nil { + return err + } + + config.Prune, err = prune.EnsureNotChanged(tx, config.Prune) + if err != nil { + return err + } + if err := snap.EnsureNotChanged(tx, config.Snapshot); err != nil { + return err + } + log.Info("Effective", "prune_flags", config.Prune.String(), "snapshot_flags", config.Snapshot.String()) + + return nil + }); err != nil { + return nil, err + } + backend.sentryControlServer, err = sentry.NewControlServer(chainKv, stack.Config().NodeName(), chainConfig, genesis.Hash(), backend.engine, backend.config.NetworkID, backend.sentries, config.BlockDownloaderWindow, blockReader) if err != nil { return nil, err diff --git a/eth/ethconsensusconfig/config.go b/eth/ethconsensusconfig/config.go index aa9a18fd662..fadd2ab887a 100644 --- a/eth/ethconsensusconfig/config.go +++ b/eth/ethconsensusconfig/config.go @@ -14,10 +14,11 @@ import ( "github.com/ledgerwatch/erigon/consensus/parlia" "github.com/ledgerwatch/erigon/consensus/serenity" "github.com/ledgerwatch/erigon/params" + "github.com/ledgerwatch/erigon/turbo/snapshotsync" "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) 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) consensus.Engine { var eng consensus.Engine switch consensusCfg := config.(type) { @@ -56,7 +57,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)) + eng = parlia.New(chainConfig, db.OpenDatabase(consensusCfg.DBPath, logger, consensusCfg.InMemory), snapshots) } case *params.BorConfig: if chainConfig.Bor != nil {