go-ethereum/eth/ethconfig/config.go
CPerezz e59c92959c
cmd, eth: improve partial state flag documentation and categorization
Move partial state CLI flags into their own "PARTIAL STATE" help category
(matching BEACON CHAIN, DEVELOPER CHAIN patterns), improve Usage strings
with examples and constraint descriptions, expand PartialStateConfig doc
comments to explain EIP-7928 implications, and raise BAL retention minimum
from 64 to 256 (required by BLOCKHASH opcode).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 12:05:26 +02:00

374 lines
14 KiB
Go

// Copyright 2021 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package ethconfig contains the configuration of the ETH and LES protocols.
package ethconfig
import (
"encoding/json"
"errors"
"fmt"
"os"
"time"
"github.com/ethereum/go-ethereum/core/types/bal"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/beacon"
"github.com/ethereum/go-ethereum/consensus/clique"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/history"
"github.com/ethereum/go-ethereum/core/txpool/blobpool"
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
"github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/triedb/pathdb"
)
// FullNodeGPO contains default gasprice oracle settings for full node.
var FullNodeGPO = gasprice.Config{
Blocks: 20,
Percentile: 60,
MaxHeaderHistory: 1024,
MaxBlockHistory: 1024,
MaxPrice: gasprice.DefaultMaxPrice,
IgnorePrice: gasprice.DefaultIgnorePrice,
}
// Defaults contains default settings for use on the Ethereum main net.
var Defaults = Config{
HistoryMode: history.KeepAll,
SyncMode: SnapSync,
NetworkId: 0, // enable auto configuration of networkID == chainID
TxLookupLimit: 2350000,
TransactionHistory: 2350000,
LogHistory: 2350000,
StateHistory: pathdb.Defaults.StateHistory,
TrienodeHistory: pathdb.Defaults.TrienodeHistory,
NodeFullValueCheckpoint: pathdb.Defaults.FullValueCheckpoint,
DatabaseCache: 2048,
TrieCleanCache: 614,
TrieDirtyCache: 1024,
SnapshotCache: 409,
TrieTimeout: 60 * time.Minute,
FilterLogCacheSize: 32,
LogQueryLimit: 1000,
Miner: miner.DefaultConfig,
TxPool: legacypool.DefaultConfig,
BlobPool: blobpool.DefaultConfig,
RPCGasCap: 50000000,
RPCEVMTimeout: 5 * time.Second,
GPO: FullNodeGPO,
RPCTxFeeCap: 1, // 1 ether
TxSyncDefaultTimeout: 20 * time.Second,
TxSyncMaxTimeout: 1 * time.Minute,
SlowBlockThreshold: -1, // Disabled by default; set via --debug.logslowblock flag
RangeLimit: 0,
PartialState: DefaultPartialStateConfig(),
}
//go:generate go run github.com/fjl/gencodec -type Config -formats toml -out gen_config.go
// Config contains configuration options for ETH and LES protocols.
type Config struct {
// The genesis block, which is inserted if the database is empty.
// If nil, the Ethereum main net block is used.
Genesis *core.Genesis `toml:",omitempty"`
// Network ID separates blockchains on the peer-to-peer networking level. When left
// zero, the chain ID is used as network ID.
NetworkId uint64
SyncMode SyncMode
// HistoryMode configures chain history retention.
HistoryMode history.HistoryMode
// This can be set to list of enrtree:// URLs which will be queried for
// nodes to connect to.
EthDiscoveryURLs []string
SnapDiscoveryURLs []string
// State options.
NoPruning bool // Whether to disable pruning and flush everything to disk
NoPrefetch bool // Whether to disable prefetching and only load state on demand
// Deprecated: use 'TransactionHistory' instead.
TxLookupLimit uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved.
TransactionHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved.
LogHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head where a log search index is maintained.
LogNoHistory bool `toml:",omitempty"` // No log search index is maintained.
LogExportCheckpoints string // export log index checkpoints to file
StateHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head whose state histories are reserved.
TrienodeHistory int64 `toml:",omitempty"` // Number of blocks from the chain head for which trienode histories are retained
// The frequency of full-value encoding. For example, a value of 16 means
// that, on average, for a given trie node across its 16 consecutive historical
// versions, only one version is stored in full format, while the others
// are stored in diff mode for storage compression.
NodeFullValueCheckpoint uint32 `toml:",omitempty"`
// State scheme represents the scheme used to store ethereum states and trie
// nodes on top. It can be 'hash', 'path', or none which means use the scheme
// consistent with persistent state.
StateScheme string `toml:",omitempty"`
// RequiredBlocks is a set of block number -> hash mappings which must be in the
// canonical chain of all remote peers. Setting the option makes geth verify the
// presence of these blocks for every new peer connection.
RequiredBlocks map[uint64]common.Hash `toml:"-"`
// SlowBlockThreshold is the block execution time threshold beyond which
// detailed statistics are logged. Negative means disabled (default), zero
// logs all blocks, positive filters by execution time.
SlowBlockThreshold time.Duration `toml:",omitempty"`
// Database options
SkipBcVersionCheck bool `toml:"-"`
DatabaseHandles int `toml:"-"`
DatabaseCache int
DatabaseFreezer string
DatabaseEra string
TrieCleanCache int
TrieDirtyCache int
TrieTimeout time.Duration
SnapshotCache int
Preimages bool
// This is the number of blocks for which logs will be cached in the filter system.
FilterLogCacheSize int
// This is the maximum number of addresses or topics allowed in filter criteria
// for eth_getLogs.
LogQueryLimit int
// Mining options
Miner miner.Config
// Transaction pool options
TxPool legacypool.Config
BlobPool blobpool.Config
// Gas Price Oracle options
GPO gasprice.Config
// Enables tracking of SHA3 preimages in the VM
EnablePreimageRecording bool
// Enables collection of witness trie access statistics
EnableWitnessStats bool
// Generate execution witnesses and self-check against them (testing purpose)
StatelessSelfValidation bool
// Enables tracking of state size
EnableStateSizeTracking bool
// Enables VM tracing
VMTrace string
VMTraceJsonConfig string
// RPCGasCap is the global gas cap for eth-call variants.
RPCGasCap uint64
// RPCEVMTimeout is the global timeout for eth-call.
RPCEVMTimeout time.Duration
// RPCTxFeeCap is the global transaction fee (price * gas limit) cap for
// send-transaction variants. The unit is ether.
RPCTxFeeCap float64
// OverrideOsaka (TODO: remove after the fork)
OverrideOsaka *uint64 `toml:",omitempty"`
// OverrideBPO1 (TODO: remove after the fork)
OverrideBPO1 *uint64 `toml:",omitempty"`
// OverrideBPO2 (TODO: remove after the fork)
OverrideBPO2 *uint64 `toml:",omitempty"`
// OverrideVerkle (TODO: remove after the fork)
OverrideVerkle *uint64 `toml:",omitempty"`
// EIP-7966: eth_sendRawTransactionSync timeouts
TxSyncDefaultTimeout time.Duration `toml:",omitempty"`
TxSyncMaxTimeout time.Duration `toml:",omitempty"`
// RangeLimit restricts the maximum range (end - start) for range queries.
RangeLimit uint64 `toml:",omitempty"`
BALExecutionMode bal.BALExecutionMode
// PartialState configures partial statefulness mode for reduced storage.
PartialState PartialStateConfig
}
// DefaultChainRetention is the default number of recent blocks for which
// bodies and receipts are retained in partial state mode. Older blocks only
// keep their headers. 1024 blocks (~3.4 hours at 12s/block) is sufficient
// for reorg handling and recent receipt lookups. Configurable via
// --partial-state.chain-retention.
const DefaultChainRetention = 1024
// PartialStateConfig configures partial statefulness mode (EIP-7928).
//
// When enabled, the node maintains the full account trie (all accounts, balances,
// nonces, code hashes) but only stores storage for explicitly tracked contracts.
// Blocks are processed using Block Access Lists (BALs) instead of re-executing
// transactions, dramatically reducing both storage requirements and CPU usage.
//
// Requires a network that supports EIP-7928 BAL propagation via the Engine API.
type PartialStateConfig struct {
// Enabled activates partial state mode. When true, snap sync downloads
// all accounts but skips storage and bytecode for untracked contracts.
Enabled bool
// Contracts is the list of contract addresses to track full storage for.
// Storage for contracts not in this list is skipped during sync, so
// eth_getStorageAt returns zero values and eth_call may produce incorrect
// results when touching untracked contracts.
Contracts []common.Address
// ContractsFile is the path to a JSON file containing contract addresses
// to track. Merged with Contracts above. See loadContractsFromFile for format.
ContractsFile string `toml:",omitempty"`
// BALRetention is the number of blocks to keep BAL history for. Must
// be at least 256 (BLOCKHASH opcode requires 256 blocks of history).
// Increase beyond 256 to support deeper reorg windows. Default 256.
BALRetention uint64
// ChainRetention is the number of recent blocks to retain bodies and
// receipts for. Older blocks only keep their headers. During sync, bodies
// and receipts outside this window are never downloaded. After sync, the
// freezer enforces a rolling window, deleting aged-out data. Set to 0 to
// keep all chain history. Default 1024 (~3.4 hours at 12s/block).
ChainRetention uint64
}
// DefaultPartialStateConfig returns the default partial state configuration.
func DefaultPartialStateConfig() PartialStateConfig {
return PartialStateConfig{
Enabled: false,
Contracts: nil,
ContractsFile: "",
BALRetention: 256,
ChainRetention: DefaultChainRetention,
}
}
// LoadPartialStateContracts loads contract addresses from a JSON file
// and merges them with any directly configured addresses.
func (c *PartialStateConfig) LoadPartialStateContracts() error {
if c.ContractsFile == "" {
return nil
}
return c.loadContractsFromFile(c.ContractsFile)
}
// loadContractsFromFile reads contract addresses from a JSON file.
// File format:
//
// {
// "version": 1,
// "contracts": [
// {"address": "0x...", "name": "WETH", "comment": "Wrapped Ether"},
// {"address": "0x...", "name": "USDC"}
// ]
// }
func (c *PartialStateConfig) loadContractsFromFile(path string) error {
data, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("failed to read contracts file: %w", err)
}
var file struct {
Version int `json:"version"`
Contracts []struct {
Address string `json:"address"`
Name string `json:"name,omitempty"`
Comment string `json:"comment,omitempty"`
} `json:"contracts"`
}
if err := json.Unmarshal(data, &file); err != nil {
return fmt.Errorf("failed to parse contracts file: %w", err)
}
// Validate version
if file.Version != 1 {
return fmt.Errorf("unsupported contracts file version: %d", file.Version)
}
// Merge contracts from file with directly configured ones
seen := make(map[common.Address]struct{})
for _, addr := range c.Contracts {
seen[addr] = struct{}{}
}
for _, contract := range file.Contracts {
addr := common.HexToAddress(contract.Address)
if addr == (common.Address{}) {
return fmt.Errorf("invalid contract address in file: %s", contract.Address)
}
if _, exists := seen[addr]; !exists {
c.Contracts = append(c.Contracts, addr)
seen[addr] = struct{}{}
}
}
return nil
}
// Validate checks the configuration for errors.
func (c *PartialStateConfig) Validate() error {
if !c.Enabled {
return nil // Nothing to validate if disabled
}
// Load contracts from file if specified
if err := c.LoadPartialStateContracts(); err != nil {
return err
}
// Validate BAL retention
if c.BALRetention < 256 {
return fmt.Errorf("BAL retention must be at least 256 blocks (for BLOCKHASH opcode support), got %d", c.BALRetention)
}
return nil
}
// CreateConsensusEngine creates a consensus engine for the given chain config.
// Clique is allowed for now to live standalone, but ethash is forbidden and can
// only exist on already merged networks.
func CreateConsensusEngine(config *params.ChainConfig, db ethdb.Database) (consensus.Engine, error) {
if config.TerminalTotalDifficulty == nil {
log.Error("Geth only supports PoS networks. Please transition legacy networks using Geth v1.13.x.")
return nil, errors.New("'terminalTotalDifficulty' is not set in genesis block")
}
// Wrap previously supported consensus engines into their post-merge counterpart
if config.Clique != nil {
return beacon.New(clique.New(config.Clique, db)), nil
}
return beacon.New(ethash.NewFaker()), nil
}