From 830b35c362edad428ce4136699100324adf679a9 Mon Sep 17 00:00:00 2001 From: minh-bq <97180373+minh-bq@users.noreply.github.com> Date: Wed, 15 Jan 2025 15:03:34 +0700 Subject: [PATCH] core: don't prune blob sidecar in archive node (#659) This commit adds a flag --no-pruning-sidecar (default: true) to disable blob sidecar pruning in archive node. Blob sidecar is meant to be pruned, but in the early state where the offchain storage is not available, it might be better to keep it in archive node for debugging. --- cmd/ronin/chaincmd.go | 1 + cmd/ronin/main.go | 1 + cmd/utils/flags.go | 21 ++++++++++++++++++++- core/blockchain.go | 3 ++- core/blockchain_test.go | 23 ++++++++++++++++++++--- eth/backend.go | 1 + eth/ethconfig/config.go | 2 ++ 7 files changed, 47 insertions(+), 5 deletions(-) diff --git a/cmd/ronin/chaincmd.go b/cmd/ronin/chaincmd.go index b53a5c8951..23a103d5dd 100644 --- a/cmd/ronin/chaincmd.go +++ b/cmd/ronin/chaincmd.go @@ -87,6 +87,7 @@ The dumpgenesis command dumps the genesis block configuration in JSON format to utils.CacheFlag, utils.SyncModeFlag, utils.GCModeFlag, + utils.NoPruningSideCarFlag, utils.SnapshotFlag, utils.CacheDatabaseFlag, utils.CacheGCFlag, diff --git a/cmd/ronin/main.go b/cmd/ronin/main.go index 5144bc14a9..553796dd96 100644 --- a/cmd/ronin/main.go +++ b/cmd/ronin/main.go @@ -100,6 +100,7 @@ var ( utils.SyncModeFlag, utils.ExitWhenSyncedFlag, utils.GCModeFlag, + utils.NoPruningSideCarFlag, utils.SnapshotFlag, utils.TxLookupLimitFlag, utils.TriesInMemoryFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 1a5377eeb0..d2bcf4c82a 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -225,6 +225,12 @@ var ( Value: "full", Category: flags.StateCategory, } + NoPruningSideCarFlag = &cli.BoolFlag{ + Name: "no-pruning-sidecar", + Usage: `Disable blob sidecar pruning in archive node`, + Value: true, + Category: flags.StateCategory, + } SnapshotFlag = &cli.BoolFlag{ Name: "snapshot", Usage: `Enables snapshot-database mode (default = enable)`, @@ -1907,6 +1913,13 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { if ctx.IsSet(GCModeFlag.Name) { cfg.NoPruning = ctx.String(GCModeFlag.Name) == "archive" } + if !cfg.NoPruning && ctx.IsSet(NoPruningSideCarFlag.Name) { + log.Warn(fmt.Sprintf("Flag --%s has no effect when gcmode is not archive", + NoPruningSideCarFlag.Name)) + } + if cfg.NoPruning && ctx.Bool(NoPruningSideCarFlag.Name) { + cfg.NoPruningSideCar = true + } if ctx.IsSet(CacheNoPrefetchFlag.Name) { cfg.NoPrefetch = ctx.Bool(CacheNoPrefetchFlag.Name) } @@ -2305,14 +2318,20 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) } + isArchive := ctx.String(GCModeFlag.Name) == "archive" + if !isArchive && ctx.IsSet(NoPruningSideCarFlag.Name) { + log.Warn(fmt.Sprintf("Flag --%s has no effect when gcmode is not archive", + NoPruningSideCarFlag.Name)) + } cache := &core.CacheConfig{ TrieCleanLimit: ethconfig.Defaults.TrieCleanCache, TrieCleanNoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name), TrieDirtyLimit: ethconfig.Defaults.TrieDirtyCache, - TrieDirtyDisabled: ctx.String(GCModeFlag.Name) == "archive", + TrieDirtyDisabled: isArchive, TrieTimeLimit: ethconfig.Defaults.TrieTimeout, SnapshotLimit: ethconfig.Defaults.SnapshotCache, Preimages: ctx.Bool(CachePreimagesFlag.Name), + NoPruningSideCar: isArchive && ctx.Bool(NoPruningSideCarFlag.Name), } if cache.TrieDirtyDisabled && !cache.Preimages { cache.Preimages = true diff --git a/core/blockchain.go b/core/blockchain.go index e8688443be..f16d23c2dc 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -139,6 +139,7 @@ type CacheConfig struct { SnapshotLimit int // Memory allowance (MB) to use for caching snapshot entries in memory Preimages bool // Whether to store preimage of trie key to the disk TriesInMemory int // The number of tries is kept in memory before pruning + NoPruningSideCar bool // Whether to disable blob sidecar pruning SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it } @@ -1486,7 +1487,7 @@ func (bc *BlockChain) reorgNeeded(localBlock *types.Block, localTd *big.Int, ext // pruneBlockSidecars prunes the sidecars of blocks that are older than the keep period func (bc *BlockChain) pruneBlockSidecars(db ethdb.KeyValueWriter, curBlock *types.Block) { - if curBlock.NumberU64() < uint64(bc.blobPrunePeriod) { + if bc.cacheConfig.NoPruningSideCar || curBlock.NumberU64() < uint64(bc.blobPrunePeriod) { return } pruneBlockNumber := curBlock.NumberU64() - uint64(bc.blobPrunePeriod) diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 265393a699..7e4adb214f 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -4223,7 +4223,15 @@ func TestInsertChainWithSidecars(t *testing.T) { wg.Wait() } -func TestSidecarsPruning(t *testing.T) { +func TestSidecarPruning(t *testing.T) { + testSidecarsPruning(t, true) +} + +func TestNoSidecarPruning(t *testing.T) { + testSidecarsPruning(t, false) +} + +func testSidecarsPruning(t *testing.T, enabled bool) { var prunePeriod uint64 = 1000 privateKey, _ := crypto.GenerateKey() address := crypto.PubkeyToAddress(privateKey.PublicKey) @@ -4244,6 +4252,9 @@ func TestSidecarsPruning(t *testing.T) { if err != nil { t.Fatalf("Failed to create blockchain, err %s", err) } + if !enabled { + chain.cacheConfig.NoPruningSideCar = true + } chain.setBlobPrunePeriod(prunePeriod) signer := types.NewCancunSigner(chainConfig.ChainID) @@ -4309,8 +4320,14 @@ func TestSidecarsPruning(t *testing.T) { pruneBlockNumber := curBlockNumber - prunePeriod pruneBlockHash := chain.GetBlockByNumber(uint64(pruneBlockNumber)).Hash() sidecars := rawdb.ReadBlobSidecars(chain.db, pruneBlockHash, uint64(pruneBlockNumber)) - if sidecars != nil { - t.Fatalf("Sidecars should be pruned at block %d", curBlockNumber-prunePeriod) + if enabled { + if sidecars != nil { + t.Fatalf("Sidecars should be pruned at block %d", curBlockNumber-prunePeriod) + } + } else { + if sidecars == nil { + t.Fatalf("Sidecars must not be pruned at block %d", curBlockNumber-prunePeriod) + } } } } diff --git a/eth/backend.go b/eth/backend.go index 52f1b0f6bf..f136042f96 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -202,6 +202,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { SnapshotLimit: config.SnapshotCache, Preimages: config.Preimages, TriesInMemory: config.TriesInMemory, + NoPruningSideCar: config.NoPruningSideCar, } ) eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, chainConfig, eth.engine, vmConfig, eth.shouldPreserve, &config.TxLookupLimit) diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 5e64069127..c3c6eda0ab 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -143,6 +143,8 @@ type Config struct { NoPruning bool // Whether to disable pruning and flush everything to disk NoPrefetch bool // Whether to disable prefetching and only load state on demand + NoPruningSideCar bool // Whether to disable blob sidecar pruning + TxLookupLimit uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved. // Whitelist of required block number -> hash values to accept