mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-10 08:51:38 +00:00
core, trie, triedb: group 2^N binary trie nodes in serialization
This commit is contained in:
parent
b0ead5e17b
commit
f99258ad36
10 changed files with 65 additions and 28 deletions
|
|
@ -455,7 +455,7 @@ func BinKeys(ctx *cli.Context) error {
|
||||||
db := triedb.NewDatabase(rawdb.NewMemoryDatabase(), triedb.UBTDefaults)
|
db := triedb.NewDatabase(rawdb.NewMemoryDatabase(), triedb.UBTDefaults)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
bt, err := genBinTrieFromAlloc(alloc, db)
|
bt, err := genBinTrieFromAlloc(alloc, db, triedb.UBTDefaults.BinTrieGroupDepth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error generating bt: %w", err)
|
return fmt.Errorf("error generating bt: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -499,7 +499,7 @@ func BinTrieRoot(ctx *cli.Context) error {
|
||||||
db := triedb.NewDatabase(rawdb.NewMemoryDatabase(), triedb.UBTDefaults)
|
db := triedb.NewDatabase(rawdb.NewMemoryDatabase(), triedb.UBTDefaults)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
bt, err := genBinTrieFromAlloc(alloc, db)
|
bt, err := genBinTrieFromAlloc(alloc, db, triedb.UBTDefaults.BinTrieGroupDepth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error generating bt: %w", err)
|
return fmt.Errorf("error generating bt: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -509,8 +509,8 @@ func BinTrieRoot(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(@CPerezz): Should this go to `bintrie` module?
|
// TODO(@CPerezz): Should this go to `bintrie` module?
|
||||||
func genBinTrieFromAlloc(alloc core.GenesisAlloc, db database.NodeDatabase) (*bintrie.BinaryTrie, error) {
|
func genBinTrieFromAlloc(alloc core.GenesisAlloc, db database.NodeDatabase, groupDepth int) (*bintrie.BinaryTrie, error) {
|
||||||
bt, err := bintrie.NewBinaryTrie(types.EmptyBinaryHash, db)
|
bt, err := bintrie.NewBinaryTrie(types.EmptyBinaryHash, db, groupDepth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ var (
|
||||||
utils.StateHistoryFlag,
|
utils.StateHistoryFlag,
|
||||||
utils.TrienodeHistoryFlag,
|
utils.TrienodeHistoryFlag,
|
||||||
utils.TrienodeHistoryFullValueCheckpointFlag,
|
utils.TrienodeHistoryFullValueCheckpointFlag,
|
||||||
|
utils.BinTrieGroupDepthFlag,
|
||||||
utils.LightKDFFlag,
|
utils.LightKDFFlag,
|
||||||
utils.EthRequiredBlocksFlag,
|
utils.EthRequiredBlocksFlag,
|
||||||
utils.LegacyWhitelistFlag, // deprecated
|
utils.LegacyWhitelistFlag, // deprecated
|
||||||
|
|
|
||||||
|
|
@ -297,6 +297,12 @@ var (
|
||||||
Value: ethconfig.Defaults.EnableStateSizeTracking,
|
Value: ethconfig.Defaults.EnableStateSizeTracking,
|
||||||
Category: flags.StateCategory,
|
Category: flags.StateCategory,
|
||||||
}
|
}
|
||||||
|
BinTrieGroupDepthFlag = &cli.IntFlag{
|
||||||
|
Name: "bintrie.groupdepth",
|
||||||
|
Usage: "Number of levels per serialized group in binary trie (1-8, default 8). Lower values create smaller groups with more nodes.",
|
||||||
|
Value: 8,
|
||||||
|
Category: flags.StateCategory,
|
||||||
|
}
|
||||||
StateHistoryFlag = &cli.Uint64Flag{
|
StateHistoryFlag = &cli.Uint64Flag{
|
||||||
Name: "history.state",
|
Name: "history.state",
|
||||||
Usage: "Number of recent blocks to retain state history for, only relevant in state.scheme=path (default = 90,000 blocks, 0 = entire chain)",
|
Usage: "Number of recent blocks to retain state history for, only relevant in state.scheme=path (default = 90,000 blocks, 0 = entire chain)",
|
||||||
|
|
@ -1815,7 +1821,10 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
cfg.TrienodeHistory = ctx.Int64(TrienodeHistoryFlag.Name)
|
cfg.TrienodeHistory = ctx.Int64(TrienodeHistoryFlag.Name)
|
||||||
}
|
}
|
||||||
if ctx.IsSet(TrienodeHistoryFullValueCheckpointFlag.Name) {
|
if ctx.IsSet(TrienodeHistoryFullValueCheckpointFlag.Name) {
|
||||||
cfg.NodeFullValueCheckpoint = uint32(ctx.Uint(TrienodeHistoryFullValueCheckpointFlag.Name))
|
cfg.TrienodeHistory = ctx.Int64(TrienodeHistoryFullValueCheckpointFlag.Name)
|
||||||
|
}
|
||||||
|
if ctx.IsSet(BinTrieGroupDepthFlag.Name) {
|
||||||
|
cfg.BinTrieGroupDepth = ctx.Int(BinTrieGroupDepthFlag.Name)
|
||||||
}
|
}
|
||||||
if ctx.IsSet(StateSchemeFlag.Name) {
|
if ctx.IsSet(StateSchemeFlag.Name) {
|
||||||
cfg.StateScheme = ctx.String(StateSchemeFlag.Name)
|
cfg.StateScheme = ctx.String(StateSchemeFlag.Name)
|
||||||
|
|
@ -2433,6 +2442,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
||||||
StateHistory: ctx.Uint64(StateHistoryFlag.Name),
|
StateHistory: ctx.Uint64(StateHistoryFlag.Name),
|
||||||
TrienodeHistory: ctx.Int64(TrienodeHistoryFlag.Name),
|
TrienodeHistory: ctx.Int64(TrienodeHistoryFlag.Name),
|
||||||
NodeFullValueCheckpoint: uint32(ctx.Uint(TrienodeHistoryFullValueCheckpointFlag.Name)),
|
NodeFullValueCheckpoint: uint32(ctx.Uint(TrienodeHistoryFullValueCheckpointFlag.Name)),
|
||||||
|
BinTrieGroupDepth: ctx.Int(BinTrieGroupDepthFlag.Name),
|
||||||
|
|
||||||
// Disable transaction indexing/unindexing.
|
// Disable transaction indexing/unindexing.
|
||||||
TxLookupLimit: -1,
|
TxLookupLimit: -1,
|
||||||
|
|
|
||||||
|
|
@ -170,9 +170,10 @@ type BlockChainConfig struct {
|
||||||
TrieNoAsyncFlush bool // Whether the asynchronous buffer flushing is disallowed
|
TrieNoAsyncFlush bool // Whether the asynchronous buffer flushing is disallowed
|
||||||
TrieJournalDirectory string // Directory path to the journal used for persisting trie data across node restarts
|
TrieJournalDirectory string // Directory path to the journal used for persisting trie data across node restarts
|
||||||
|
|
||||||
Preimages bool // Whether to store preimage of trie key to the disk
|
Preimages bool // Whether to store preimage of trie key to the disk
|
||||||
StateScheme string // Scheme used to store ethereum states and merkle tree nodes on top
|
StateScheme string // Scheme used to store ethereum states and merkle tree nodes on top
|
||||||
ArchiveMode bool // Whether to enable the archive mode
|
ArchiveMode bool // Whether to enable the archive mode
|
||||||
|
BinTrieGroupDepth int // Number of levels per serialized group in binary trie (1-8)
|
||||||
|
|
||||||
// Number of blocks from the chain head for which state histories are retained.
|
// Number of blocks from the chain head for which state histories are retained.
|
||||||
// If set to 0, all state histories across the entire chain will be retained;
|
// If set to 0, all state histories across the entire chain will be retained;
|
||||||
|
|
@ -258,10 +259,11 @@ func (cfg BlockChainConfig) WithNoAsyncFlush(on bool) *BlockChainConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
// triedbConfig derives the configures for trie database.
|
// triedbConfig derives the configures for trie database.
|
||||||
func (cfg *BlockChainConfig) triedbConfig(isUBT bool) *triedb.Config {
|
func (cfg *BlockChainConfig) triedbConfig(isVerkle bool) *triedb.Config {
|
||||||
config := &triedb.Config{
|
config := &triedb.Config{
|
||||||
Preimages: cfg.Preimages,
|
Preimages: cfg.Preimages,
|
||||||
IsUBT: isUBT,
|
IsVerkle: isVerkle,
|
||||||
|
BinTrieGroupDepth: cfg.BinTrieGroupDepth,
|
||||||
}
|
}
|
||||||
if cfg.StateScheme == rawdb.HashScheme {
|
if cfg.StateScheme == rawdb.HashScheme {
|
||||||
config.HashDB = &hashdb.Config{
|
config.HashDB = &hashdb.Config{
|
||||||
|
|
|
||||||
|
|
@ -237,6 +237,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||||
StateHistory: config.StateHistory,
|
StateHistory: config.StateHistory,
|
||||||
TrienodeHistory: config.TrienodeHistory,
|
TrienodeHistory: config.TrienodeHistory,
|
||||||
NodeFullValueCheckpoint: config.NodeFullValueCheckpoint,
|
NodeFullValueCheckpoint: config.NodeFullValueCheckpoint,
|
||||||
|
BinTrieGroupDepth: config.BinTrieGroupDepth,
|
||||||
StateScheme: scheme,
|
StateScheme: scheme,
|
||||||
HistoryPolicy: histPolicy,
|
HistoryPolicy: histPolicy,
|
||||||
TxLookupLimit: int64(min(config.TransactionHistory, math.MaxInt64)),
|
TxLookupLimit: int64(min(config.TransactionHistory, math.MaxInt64)),
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ var Defaults = Config{
|
||||||
StateHistory: pathdb.Defaults.StateHistory,
|
StateHistory: pathdb.Defaults.StateHistory,
|
||||||
TrienodeHistory: pathdb.Defaults.TrienodeHistory,
|
TrienodeHistory: pathdb.Defaults.TrienodeHistory,
|
||||||
NodeFullValueCheckpoint: pathdb.Defaults.FullValueCheckpoint,
|
NodeFullValueCheckpoint: pathdb.Defaults.FullValueCheckpoint,
|
||||||
|
BinTrieGroupDepth: 8, // byte-aligned groups by default
|
||||||
DatabaseCache: 2048,
|
DatabaseCache: 2048,
|
||||||
TrieCleanCache: 614,
|
TrieCleanCache: 614,
|
||||||
TrieDirtyCache: 1024,
|
TrieDirtyCache: 1024,
|
||||||
|
|
@ -125,6 +126,11 @@ type Config struct {
|
||||||
// consistent with persistent state.
|
// consistent with persistent state.
|
||||||
StateScheme string `toml:",omitempty"`
|
StateScheme string `toml:",omitempty"`
|
||||||
|
|
||||||
|
// BinTrieGroupDepth is the number of levels per serialized group in binary trie.
|
||||||
|
// Valid values are 1-8, with 8 being the default (byte-aligned groups).
|
||||||
|
// Lower values create smaller groups with more nodes.
|
||||||
|
BinTrieGroupDepth int `toml:",omitempty"`
|
||||||
|
|
||||||
// RequiredBlocks is a set of block number -> hash mappings which must be in the
|
// 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
|
// canonical chain of all remote peers. Setting the option makes geth verify the
|
||||||
// presence of these blocks for every new peer connection.
|
// presence of these blocks for every new peer connection.
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
||||||
TrienodeHistory int64 `toml:",omitempty"`
|
TrienodeHistory int64 `toml:",omitempty"`
|
||||||
NodeFullValueCheckpoint uint32 `toml:",omitempty"`
|
NodeFullValueCheckpoint uint32 `toml:",omitempty"`
|
||||||
StateScheme string `toml:",omitempty"`
|
StateScheme string `toml:",omitempty"`
|
||||||
|
BinTrieGroupDepth int `toml:",omitempty"`
|
||||||
RequiredBlocks map[uint64]common.Hash `toml:"-"`
|
RequiredBlocks map[uint64]common.Hash `toml:"-"`
|
||||||
SlowBlockThreshold time.Duration `toml:",omitempty"`
|
SlowBlockThreshold time.Duration `toml:",omitempty"`
|
||||||
SkipBcVersionCheck bool `toml:"-"`
|
SkipBcVersionCheck bool `toml:"-"`
|
||||||
|
|
@ -87,6 +88,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
||||||
enc.TrienodeHistory = c.TrienodeHistory
|
enc.TrienodeHistory = c.TrienodeHistory
|
||||||
enc.NodeFullValueCheckpoint = c.NodeFullValueCheckpoint
|
enc.NodeFullValueCheckpoint = c.NodeFullValueCheckpoint
|
||||||
enc.StateScheme = c.StateScheme
|
enc.StateScheme = c.StateScheme
|
||||||
|
enc.BinTrieGroupDepth = c.BinTrieGroupDepth
|
||||||
enc.RequiredBlocks = c.RequiredBlocks
|
enc.RequiredBlocks = c.RequiredBlocks
|
||||||
enc.SlowBlockThreshold = c.SlowBlockThreshold
|
enc.SlowBlockThreshold = c.SlowBlockThreshold
|
||||||
enc.SkipBcVersionCheck = c.SkipBcVersionCheck
|
enc.SkipBcVersionCheck = c.SkipBcVersionCheck
|
||||||
|
|
@ -144,6 +146,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
||||||
TrienodeHistory *int64 `toml:",omitempty"`
|
TrienodeHistory *int64 `toml:",omitempty"`
|
||||||
NodeFullValueCheckpoint *uint32 `toml:",omitempty"`
|
NodeFullValueCheckpoint *uint32 `toml:",omitempty"`
|
||||||
StateScheme *string `toml:",omitempty"`
|
StateScheme *string `toml:",omitempty"`
|
||||||
|
BinTrieGroupDepth *int `toml:",omitempty"`
|
||||||
RequiredBlocks map[uint64]common.Hash `toml:"-"`
|
RequiredBlocks map[uint64]common.Hash `toml:"-"`
|
||||||
SlowBlockThreshold *time.Duration `toml:",omitempty"`
|
SlowBlockThreshold *time.Duration `toml:",omitempty"`
|
||||||
SkipBcVersionCheck *bool `toml:"-"`
|
SkipBcVersionCheck *bool `toml:"-"`
|
||||||
|
|
@ -234,6 +237,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
||||||
if dec.StateScheme != nil {
|
if dec.StateScheme != nil {
|
||||||
c.StateScheme = *dec.StateScheme
|
c.StateScheme = *dec.StateScheme
|
||||||
}
|
}
|
||||||
|
if dec.BinTrieGroupDepth != nil {
|
||||||
|
c.BinTrieGroupDepth = *dec.BinTrieGroupDepth
|
||||||
|
}
|
||||||
if dec.RequiredBlocks != nil {
|
if dec.RequiredBlocks != nil {
|
||||||
c.RequiredBlocks = dec.RequiredBlocks
|
c.RequiredBlocks = dec.RequiredBlocks
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ const (
|
||||||
NodeTypeBytes = 1 // Size of node type prefix in serialization
|
NodeTypeBytes = 1 // Size of node type prefix in serialization
|
||||||
HashSize = 32 // Size of a hash in bytes
|
HashSize = 32 // Size of a hash in bytes
|
||||||
StemBitmapSize = 32 // Size of the bitmap in a stem node (256 values = 32 bytes)
|
StemBitmapSize = 32 // Size of the bitmap in a stem node (256 values = 32 bytes)
|
||||||
|
|
||||||
|
MaxGroupDepth = 8
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
||||||
|
|
@ -107,9 +107,10 @@ func ChunkifyCode(code []byte) ChunkedCode {
|
||||||
|
|
||||||
// BinaryTrie is the implementation of https://eips.ethereum.org/EIPS/eip-7864.
|
// BinaryTrie is the implementation of https://eips.ethereum.org/EIPS/eip-7864.
|
||||||
type BinaryTrie struct {
|
type BinaryTrie struct {
|
||||||
store *nodeStore
|
root BinaryNode
|
||||||
reader *trie.Reader
|
reader *trie.Reader
|
||||||
tracer *trie.PrevalueTracer
|
tracer *trie.PrevalueTracer
|
||||||
|
groupDepth int // Number of levels per serialized group (1-8, default 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToDot converts the binary trie to a DOT language representation. Useful for debugging.
|
// ToDot converts the binary trie to a DOT language representation. Useful for debugging.
|
||||||
|
|
@ -119,15 +120,20 @@ func (t *BinaryTrie) ToDot() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBinaryTrie creates a new binary trie.
|
// NewBinaryTrie creates a new binary trie.
|
||||||
func NewBinaryTrie(root common.Hash, db database.NodeDatabase) (*BinaryTrie, error) {
|
// groupDepth specifies the number of levels per serialized group (1-8).
|
||||||
|
func NewBinaryTrie(root common.Hash, db database.NodeDatabase, groupDepth int) (*BinaryTrie, error) {
|
||||||
|
if groupDepth < 1 || groupDepth > MaxGroupDepth {
|
||||||
|
groupDepth = MaxGroupDepth // Default to 8
|
||||||
|
}
|
||||||
reader, err := trie.NewReader(root, common.Hash{}, db)
|
reader, err := trie.NewReader(root, common.Hash{}, db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
t := &BinaryTrie{
|
t := &BinaryTrie{
|
||||||
store: newNodeStore(),
|
root: NewBinaryNode(),
|
||||||
reader: reader,
|
reader: reader,
|
||||||
tracer: trie.NewPrevalueTracer(),
|
tracer: trie.NewPrevalueTracer(),
|
||||||
|
groupDepth: groupDepth,
|
||||||
}
|
}
|
||||||
// Parse the root node if it's not empty
|
// Parse the root node if it's not empty
|
||||||
if root != types.EmptyBinaryHash && root != types.EmptyRootHash {
|
if root != types.EmptyBinaryHash && root != types.EmptyRootHash {
|
||||||
|
|
@ -341,9 +347,10 @@ func (t *BinaryTrie) Prove(key []byte, proofDb ethdb.KeyValueWriter) error {
|
||||||
// Copy creates a deep copy of the trie.
|
// Copy creates a deep copy of the trie.
|
||||||
func (t *BinaryTrie) Copy() *BinaryTrie {
|
func (t *BinaryTrie) Copy() *BinaryTrie {
|
||||||
return &BinaryTrie{
|
return &BinaryTrie{
|
||||||
store: t.store.Copy(),
|
root: t.root.Copy(),
|
||||||
reader: t.reader,
|
reader: t.reader,
|
||||||
tracer: t.tracer.Copy(),
|
tracer: t.tracer.Copy(),
|
||||||
|
groupDepth: t.groupDepth,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,10 +31,11 @@ import (
|
||||||
|
|
||||||
// Config defines all necessary options for database.
|
// Config defines all necessary options for database.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Preimages bool // Flag whether the preimage of node key is recorded
|
Preimages bool // Flag whether the preimage of node key is recorded
|
||||||
IsUBT bool // Flag whether the db is holding a verkle tree
|
IsVerkle bool // Flag whether the db is holding a verkle tree
|
||||||
HashDB *hashdb.Config // Configs for hash-based scheme
|
BinTrieGroupDepth int // Number of levels per serialized group in binary trie (1-8, default 8)
|
||||||
PathDB *pathdb.Config // Configs for experimental path-based scheme
|
HashDB *hashdb.Config // Configs for hash-based scheme
|
||||||
|
PathDB *pathdb.Config // Configs for experimental path-based scheme
|
||||||
}
|
}
|
||||||
|
|
||||||
// HashDefaults represents a config for using hash-based scheme with
|
// HashDefaults represents a config for using hash-based scheme with
|
||||||
|
|
@ -48,9 +49,10 @@ var HashDefaults = &Config{
|
||||||
// UBTDefaults represents a config for holding verkle trie data
|
// UBTDefaults represents a config for holding verkle trie data
|
||||||
// using path-based scheme with default settings.
|
// using path-based scheme with default settings.
|
||||||
var UBTDefaults = &Config{
|
var UBTDefaults = &Config{
|
||||||
Preimages: false,
|
Preimages: false,
|
||||||
IsUBT: true,
|
IsUBT: true,
|
||||||
PathDB: pathdb.Defaults,
|
BinTrieGroupDepth: 8, // Default to byte-aligned groups
|
||||||
|
PathDB: pathdb.Defaults,
|
||||||
}
|
}
|
||||||
|
|
||||||
// backend defines the methods needed to access/update trie nodes in different
|
// backend defines the methods needed to access/update trie nodes in different
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue