mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-23 13:16:42 +00:00
Co-authored-by: Ignacio Hagopian <jsign.uy@gmail.com> fix tests in https://github.com/ethereum/go-ethereum/pull/32445 (#548) * fix tests * fix MakePreState not respecting verkle flag bring in verkle iterator and verkle subcommand (#549) push missing verkle iterator files (#550) fix rebase issue cmd/evm/internal/t8n: Binary at genesis support - Verkle <-> Binary swap (#552) * remove: Verkle-related files with no codebase deps * fixup * refactor: update Prestate and transition logic for binary trie support - Introduced a new field `BT` in the `Prestate` struct to accommodate binary trie data. - Updated the `MakePreState` function to replace the `verkle` flag with `isBintrie` for better clarity. - Renamed functions and variables related to Verkle to their binary trie counterparts, including `BinKey`, `BinKeys`, and `BinTrieRoot`. - Added TODO comments for further updates and clarifications regarding the transition from Verkle to binary trie structures. * feat: add ChunkifyCode function for EVM bytecode chunking - Introduced the `ChunkedCode` type to represent 32-byte chunks of EVM bytecode. - Implemented the `ChunkifyCode` function to convert a byte array of EVM bytecode into chunked format. - Updated the `UpdateContractCode` method to utilize the new `ChunkifyCode` function. * refactor: rename Verkle commands to Binary Trie equivalents We leave the command name equal to keep support with https://github.com/ethereum/execution-spec-tests/tree/verkle/main * refactor: update flags and transition logic for Binary Trie support - Renamed `OutputVKTFlag` to `OutputBTFlag`. - Renamed `InputVKTFlag` to `InputBTFlag` and updated its usage description for prestate input. - Adjusted `Transition` function to utilize the new `BT` field for Binary Trie data instead of Verkle. - Updated `dispatchOutput` function to handle Binary Trie output correctly. * refactor: update DumpVKTLeaves to DumpBinTrieLeaves and adjust trie usage * refactor: update functions and comments for Binary Trie implementation - Replaced references to Verkle Trie with Binary Trie in various functions. - Updated `genBinTrieFromAlloc` to return a Binary Trie instead of a Verkle Trie. - Adjusted output functions to utilize Binary Trie methods and updated associated comments. * refactor: rename flags for Binary Trie integration * feat: add BinaryCodeChunkKey and BinaryCodeChunkCode functions for code chunking - Introduced `BinaryCodeChunkKey` to compute the tree key of a code-chunk for a given address. - Added `BinaryCodeChunkCode` to return the chunkification of bytecode. * feat: introduce TransitionTrie for Binary Trie integration - Added a new `TransitionTrie` type to facilitate the integration of the Binary Trie with the existing MPT trie. - Updated the `newTrieReader` function to utilize the new `TransitionTrie` implementation. - The transition tree has been moved to its own package `core/state/transitiontrie`, resolving the import cycle issue we get into when including `BinaryTrie` within `database.go`/ * refactor: update references to TransitionTrie and BinaryTrie integration - Replaced instances of `bintrie.BinaryTrie` with `transitiontrie.TransitionTrie` in the `execution.go`, `dump.go`, and `reader.go`. - Adjusted the `newTrieReader` function with atemporary workaround for import cycles. * trie/bintrie: fix StemNode serialization to only return actual data This fixes the "invalid serialized node length" error that occurred when Binary Trie nodes were persisted and later reloaded from the database. Issue Discovery: The error manifested when running execution-spec-tests with Binary Trie mode. After committing state changes, attempting to create a new StateDB with the committed root would fail with "invalid serialized node length" when deserializing the root node. Root Cause Analysis: Through debug logging, discovered that: 1. StemNodes were being serialized with 97 bytes of actual data 2. But the SerializeNode function was returning the entire 8224-byte buffer 3. When the node was later loaded and deserialized, it received 97 bytes 4. The deserializer expected at least 128 bytes for the bitmap and values 5. This mismatch caused the deserialization to fail The Fix: Changed SerializeNode to return only the actual data (serialized[:offset]) instead of the entire pre-allocated buffer (serialized[:]). This ensures that only the meaningful bytes are persisted to the database. This aligns the serialization with the deserialization logic, which correctly handles variable-length StemNode data based on which values are actually present in the node. * Fix Binary Trie StemNode serialization array size calculation This fixes a critical off-by-one error in the StemNode serialization buffer that was causing "invalid serialized node length" errors during execution-spec-tests. The error was discovered when running execution-spec-tests with Binary Trie mode: ``` cd ../execution-spec-tests && uv run fill --fork Verkle -v -m blockchain_test \ -k test_contract_creation -n 1 --evm-bin=PATH_TO/go-ethereum/evm ``` The tests were failing with: ``` ERROR: error getting prestate: invalid serialized node length ``` Through systematic debugging with hex dumps and bitmap analysis, we discovered that the serialized array was incorrectly sized: **Incorrect**: `var serialized [32 + 32 + 256*32]byte` - This allocated: 32 + 32 + 8192 = 8256 bytes - Missing 1 byte for the node type prefix **Correct**: `var serialized [1 + 31 + 32 + 256*32]byte` - This allocates: 1 + 31 + 32 + 8192 = 8256 bytes - Properly accounts for all fields per EIP-7864 The layout should be: - 1 byte: node type (nodeTypeStem) - 31 bytes: stem (path prefix) - 32 bytes: bitmap indicating which of 256 values are present - Up to 256*32 bytes: the actual values (32 bytes each) 1. Corrected array size from `[32 + 32 + 256*32]` to `[1 + 31 + 32 + 256*32]` 2. Cleaned up type assertions to use `n` from the type switch instead of `node.(*StemNode)` 3. This ensures proper alignment of all fields during serialization The misalignment was causing the deserializer to interpret value data as bitmap data, leading to impossible bitmap patterns (e.g., 122 bits set requiring 3904 bytes when only 97 bytes were available). After this fix, the "invalid serialized node length" errors are completely resolved. The execution-spec-tests now progress past the serialization stage, confirming that Binary Trie nodes are being correctly serialized and deserialized. * various tweaks 1. move the transition trie package to trie, as this will be requested by the geth team and it's where it belongs. 2. panic if state creation has failed in execution.go, to catch issues early. 3. use a BinaryTrie and not a TransitionTrie, as evm t8n doesn't support state trie transitions at this stage. * more replacements of TransitionTrie with VerkleTrie 1. TransitionTrie doesn't work at this stage, we are only testing the binary trees at genesis, so let's make sure TransitionTrie isn't activated anywhere. 2. There was a superfluous check for Transitioned(), which actually made the code take the wrong turn: if the verkle fork has occured, and if the transition isn't in progress, it means that the conversion has ended* * to be complete, it could be that this is in the period before the start of the iterator sweep, but in that case the transition tree also needs to be returned. So there is a missing granularity in this code, but it's ok at this stage since the transition isn't supported yet. * fix(state): Use BinaryTrie instead of VerkleTrie when IsVerkle is set The codebase uses IsVerkle flag to indicate Binary Trie mode (not renamed to avoid large diff). However, OpenTrie was incorrectly creating a VerkleTrie which expects Verkle node format, while we store Binary Trie nodes. This mismatch caused "invalid serialized node length" errors when VerkleTrie tried to deserialize Binary Trie nodes. We left some instantiation of `VerkleTree` arround which we have found and changed too here. * fix(bintrie): Remove incorrect type assertion in BinaryTrie.Commit The Commit function incorrectly assumed that the root node was always an InternalNode, causing a panic when the root was a StemNode: "interface conversion: bintrie.BinaryNode is *bintrie.StemNode, not *bintrie.InternalNode" Changes: - Remove type assertion `root := t.root.(*InternalNode)` - Call CollectNodes directly on t.root which works for any BinaryNode type - Add comment explaining the root can be any BinaryNode type This fix allows BinaryTrie to properly commit trees where the root is a StemNode, which can happen in small tries or during initial setup. * fix(t8ntool): Add error handling and debug logging to MakePreState Previously, state.New errors were silently ignored, leading to nil pointer panics later when statedb was accessed. This made debugging difficult as the actual error was hidden. Changes: - Add explicit error checking when creating initial statedb - Add explicit error checking when re-opening statedb after commit - Include meaningful error messages with context (e.g., root hash) * fix(bintrie): Fix iterator to properly handle StemNode leaf values This commit fixes two in the BinaryTrie iterator: 1. Fixed Leaf() method to only return true when positioned at a specific non-nil value within a StemNode, not just at the StemNode itself. The iterator tracks position using an Index that points to the NEXT position after the current value. 2. Fixed stack underflow in Next() method by checking if we're at the root before popping from the stack. This prevents index out of range errors when iterating through the tree. These fixes resolve panics in DumpBinTrieLeaves when generating VKT output for Binary Tries in the t8n tool. * fix: handle nil child nodes in BinaryTrie InternalNode When inserting values into an InternalNode with nil children, the code was attempting to dereference nil pointers, causing panics. This fix ensures that nil children are initialized to Empty{} nodes before attempting to call methods on them. This resolves crashes when building the Binary Trie from an empty or sparse initial state. * fix: preserve Binary Trie in Apply after commit When in Binary Trie mode (isEIP4762), the state.New() call after commit was creating a new StateDB with MPT trie, losing the Binary Trie. This resulted in nil trie when attempting to dump Binary Trie leaves. Fix: Skip state.New() for Binary Trie mode since the trie is already correct after commit. Only reopen state for MPT mode. * fix(t8n): preserve Binary Trie after commit and use correct JSON field name This commit fixes two issues that prevented VKT (Binary Trie) data from being correctly generated and passed to execution-spec-tests: 1. Binary Trie Preservation (execution.go): After statedb.Commit(), the code was calling state.New() which recreated the StateDB with an MPT trie, losing the Binary Trie. For Binary Trie mode (EIP-4762), we now skip state.New() since the trie is already correct after commit. 2. JSON Field Name (transition.go): The dispatch function was using name="bt" which created a JSON output field called "bt", but execution-spec-tests expects the field to be called "vkt" for compatibility with the upstream implementation. Changed to use name="vkt" instead. So translating, I'm dumb and I shouldn't have changed them.. These fixes allow execution-spec-tests to successfully extract Binary Trie leaf data from t8n output via stdout JSON parsing. Fixes test failures in: - tests/verkle/eip6800_genesis_verkle_tree/test_contract_creation.py * fix(t8n): revert change to avoid hardcoded MPT creation. Prior, the code was working such that we were getting `nil` when re-opening. We weren't using `TransitionTree` thus reader and other interfaces were working hardcoded to MPT. This was fixed in prev. commits. Thus, this was no longer needed. * fix(t8ntool, bintrie): address PR review comments * fix(t8ntool): update JSON field name for Binary Trie in Prestate There was a leftover as we modified already in `transition.go` flagnames to be `vkt` again and prevent errors for now. * refactor: use named constants for binary node serialization sizes Replace magic numbers with named constants for better code clarity: - NodeTypeBytes = 1 (size of node type prefix) - HashSize = 32 (size of a hash) - BitmapSize = 32 (size of the bitmap in stem nodes) This makes the serialization format more self-documenting and easier to maintain. * refactor: replace magic numbers with named constants in Binary Trie Replace hardcoded values (31, 32, 256) with named constants throughout the Binary Trie implementation for improved code maintainability. - Add NodeWidth (256), StemSize (31), HashSize (32), BitmapSize (32), NodeTypeBytes (1) constants - Update all serialization, deserialization, and node operations to use constants - Revert error wrapping to maintain test compatibility * feat: add GetBinaryTreeKeyBasicData function for Binary Trie Implement GetBinaryTreeKeyBasicData function similar to GetBinaryTreeKeyCodeHash but with offset 0 (BasicDataLeafKey) instead of 1, as per EIP-7864 tree embedding spec. * fix(t8ntool, bintrie): leftovers overlooked from review addressed * fix(bintrie): rename NodeWidth to StemNodeWidth throughout package The constant NodeWidth was renamed to StemNodeWidth to better reflect its purpose as the number of children per stem node (256 values). This change ensures consistency across the Binary Trie implementation and aligns with the EIP-7864 specification for Binary Merkle Tree format. Changes made: - Updated constant definition in binary_node.go from NodeWidth to StemNodeWidth - Replaced all references across the bintrie package files - Ensures compilation succeeds and all tests pass This fix was necessary after recent refactoring of the Binary Trie code that replaced the Verkle tree implementation at genesis. --------- Co-authored-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com> fix: implement InsertValuesAtStem for HashedNode in Binary Trie (#554) This fixes the "insertValuesAtStem not implemented for hashed node" error that was blocking contract creation tests in Binary Trie mode. The implementation follows the pattern established in InternalNode.GetValuesAtStem: 1. Generate the path for the node's position in the tree 2. Resolve the hashed node to get actual node data from the database 3. Deserialize the resolved data into a concrete node type 4. Call InsertValuesAtStem on the resolved node This allows the Binary Trie to handle cases where parts of the tree are not in memory but need to be modified during state transitions, maintaining the lazy-loading design.
314 lines
12 KiB
Go
314 lines
12 KiB
Go
// Copyright 2017 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 state
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/common/lru"
|
|
"github.com/ethereum/go-ethereum/core/overlay"
|
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
"github.com/ethereum/go-ethereum/crypto"
|
|
"github.com/ethereum/go-ethereum/ethdb"
|
|
"github.com/ethereum/go-ethereum/trie"
|
|
"github.com/ethereum/go-ethereum/trie/bintrie"
|
|
"github.com/ethereum/go-ethereum/trie/transitiontrie"
|
|
"github.com/ethereum/go-ethereum/trie/trienode"
|
|
"github.com/ethereum/go-ethereum/trie/utils"
|
|
"github.com/ethereum/go-ethereum/triedb"
|
|
)
|
|
|
|
const (
|
|
// Number of codehash->size associations to keep.
|
|
codeSizeCacheSize = 1_000_000 // 4 megabytes in total
|
|
|
|
// Cache size granted for caching clean code.
|
|
codeCacheSize = 256 * 1024 * 1024
|
|
|
|
// Number of address->curve point associations to keep.
|
|
pointCacheSize = 4096
|
|
)
|
|
|
|
// Database wraps access to tries and contract code.
|
|
type Database interface {
|
|
// Reader returns a state reader associated with the specified state root.
|
|
Reader(root common.Hash) (Reader, error)
|
|
|
|
// OpenTrie opens the main account trie.
|
|
OpenTrie(root common.Hash) (Trie, error)
|
|
|
|
// OpenStorageTrie opens the storage trie of an account.
|
|
OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, trie Trie) (Trie, error)
|
|
|
|
// PointCache returns the cache holding points used in verkle tree key computation
|
|
PointCache() *utils.PointCache
|
|
|
|
// TrieDB returns the underlying trie database for managing trie nodes.
|
|
TrieDB() *triedb.Database
|
|
|
|
// Snapshot returns the underlying state snapshot.
|
|
Snapshot() *snapshot.Tree
|
|
}
|
|
|
|
// Trie is a Ethereum Merkle Patricia trie.
|
|
type Trie interface {
|
|
// GetKey returns the sha3 preimage of a hashed key that was previously used
|
|
// to store a value.
|
|
//
|
|
// TODO(fjl): remove this when StateTrie is removed
|
|
GetKey([]byte) []byte
|
|
|
|
// GetAccount abstracts an account read from the trie. It retrieves the
|
|
// account blob from the trie with provided account address and decodes it
|
|
// with associated decoding algorithm. If the specified account is not in
|
|
// the trie, nil will be returned. If the trie is corrupted(e.g. some nodes
|
|
// are missing or the account blob is incorrect for decoding), an error will
|
|
// be returned.
|
|
GetAccount(address common.Address) (*types.StateAccount, error)
|
|
|
|
// PrefetchAccount attempts to resolve specific accounts from the database
|
|
// to accelerate subsequent trie operations.
|
|
PrefetchAccount([]common.Address) error
|
|
|
|
// GetStorage returns the value for key stored in the trie. The value bytes
|
|
// must not be modified by the caller. If a node was not found in the database,
|
|
// a trie.MissingNodeError is returned.
|
|
GetStorage(addr common.Address, key []byte) ([]byte, error)
|
|
|
|
// PrefetchStorage attempts to resolve specific storage slots from the database
|
|
// to accelerate subsequent trie operations.
|
|
PrefetchStorage(addr common.Address, keys [][]byte) error
|
|
|
|
// UpdateAccount abstracts an account write to the trie. It encodes the
|
|
// provided account object with associated algorithm and then updates it
|
|
// in the trie with provided address.
|
|
UpdateAccount(address common.Address, account *types.StateAccount, codeLen int) error
|
|
|
|
// UpdateStorage associates key with value in the trie. If value has length zero,
|
|
// any existing value is deleted from the trie. The value bytes must not be modified
|
|
// by the caller while they are stored in the trie. If a node was not found in the
|
|
// database, a trie.MissingNodeError is returned.
|
|
UpdateStorage(addr common.Address, key, value []byte) error
|
|
|
|
// DeleteAccount abstracts an account deletion from the trie.
|
|
DeleteAccount(address common.Address) error
|
|
|
|
// DeleteStorage removes any existing value for key from the trie. If a node
|
|
// was not found in the database, a trie.MissingNodeError is returned.
|
|
DeleteStorage(addr common.Address, key []byte) error
|
|
|
|
// UpdateContractCode abstracts code write to the trie. It is expected
|
|
// to be moved to the stateWriter interface when the latter is ready.
|
|
UpdateContractCode(address common.Address, codeHash common.Hash, code []byte) error
|
|
|
|
// Hash returns the root hash of the trie. It does not write to the database and
|
|
// can be used even if the trie doesn't have one.
|
|
Hash() common.Hash
|
|
|
|
// Commit collects all dirty nodes in the trie and replace them with the
|
|
// corresponding node hash. All collected nodes(including dirty leaves if
|
|
// collectLeaf is true) will be encapsulated into a nodeset for return.
|
|
// The returned nodeset can be nil if the trie is clean(nothing to commit).
|
|
// Once the trie is committed, it's not usable anymore. A new trie must
|
|
// be created with new root and updated trie database for following usage
|
|
Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet)
|
|
|
|
// Witness returns a set containing all trie nodes that have been accessed.
|
|
// The returned map could be nil if the witness is empty.
|
|
Witness() map[string][]byte
|
|
|
|
// NodeIterator returns an iterator that returns nodes of the trie. Iteration
|
|
// starts at the key after the given start key. And error will be returned
|
|
// if fails to create node iterator.
|
|
NodeIterator(startKey []byte) (trie.NodeIterator, error)
|
|
|
|
// Prove constructs a Merkle proof for key. The result contains all encoded nodes
|
|
// on the path to the value at key. The value itself is also included in the last
|
|
// node and can be retrieved by verifying the proof.
|
|
//
|
|
// If the trie does not contain a value for key, the returned proof contains all
|
|
// nodes of the longest existing prefix of the key (at least the root), ending
|
|
// with the node that proves the absence of the key.
|
|
Prove(key []byte, proofDb ethdb.KeyValueWriter) error
|
|
|
|
// IsVerkle returns true if the trie is verkle-tree based
|
|
IsVerkle() bool
|
|
}
|
|
|
|
// CachingDB is an implementation of Database interface. It leverages both trie and
|
|
// state snapshot to provide functionalities for state access. It's meant to be a
|
|
// long-live object and has a few caches inside for sharing between blocks.
|
|
type CachingDB struct {
|
|
disk ethdb.KeyValueStore
|
|
triedb *triedb.Database
|
|
snap *snapshot.Tree
|
|
codeCache *lru.SizeConstrainedCache[common.Hash, []byte]
|
|
codeSizeCache *lru.Cache[common.Hash, int]
|
|
pointCache *utils.PointCache
|
|
|
|
// Transition-specific fields
|
|
TransitionStatePerRoot *lru.Cache[common.Hash, *overlay.TransitionState]
|
|
}
|
|
|
|
// NewDatabase creates a state database with the provided data sources.
|
|
func NewDatabase(triedb *triedb.Database, snap *snapshot.Tree) *CachingDB {
|
|
return &CachingDB{
|
|
disk: triedb.Disk(),
|
|
triedb: triedb,
|
|
snap: snap,
|
|
codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize),
|
|
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize),
|
|
pointCache: utils.NewPointCache(pointCacheSize),
|
|
TransitionStatePerRoot: lru.NewCache[common.Hash, *overlay.TransitionState](1000),
|
|
}
|
|
}
|
|
|
|
// NewDatabaseForTesting is similar to NewDatabase, but it initializes the caching
|
|
// db by using an ephemeral memory db with default config for testing.
|
|
func NewDatabaseForTesting() *CachingDB {
|
|
return NewDatabase(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil), nil)
|
|
}
|
|
|
|
// Reader returns a state reader associated with the specified state root.
|
|
func (db *CachingDB) Reader(stateRoot common.Hash) (Reader, error) {
|
|
var readers []StateReader
|
|
|
|
// Configure the state reader using the standalone snapshot in hash mode.
|
|
// This reader offers improved performance but is optional and only
|
|
// partially useful if the snapshot is not fully generated.
|
|
if db.TrieDB().Scheme() == rawdb.HashScheme && db.snap != nil {
|
|
snap := db.snap.Snapshot(stateRoot)
|
|
if snap != nil {
|
|
readers = append(readers, newFlatReader(snap))
|
|
}
|
|
}
|
|
// Configure the state reader using the path database in path mode.
|
|
// This reader offers improved performance but is optional and only
|
|
// partially useful if the snapshot data in path database is not
|
|
// fully generated.
|
|
if db.TrieDB().Scheme() == rawdb.PathScheme {
|
|
reader, err := db.triedb.StateReader(stateRoot)
|
|
if err == nil {
|
|
readers = append(readers, newFlatReader(reader))
|
|
}
|
|
}
|
|
// Configure the trie reader, which is expected to be available as the
|
|
// gatekeeper unless the state is corrupted.
|
|
tr, err := newTrieReader(stateRoot, db.triedb, db.pointCache)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
readers = append(readers, tr)
|
|
|
|
combined, err := newMultiStateReader(readers...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return newReader(newCachingCodeReader(db.disk, db.codeCache, db.codeSizeCache), combined), nil
|
|
}
|
|
|
|
// ReadersWithCacheStats creates a pair of state readers sharing the same internal cache and
|
|
// same backing Reader, but exposing separate statistics.
|
|
// and statistics.
|
|
func (db *CachingDB) ReadersWithCacheStats(stateRoot common.Hash) (ReaderWithStats, ReaderWithStats, error) {
|
|
reader, err := db.Reader(stateRoot)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
shared := newReaderWithCache(reader)
|
|
return newReaderWithCacheStats(shared), newReaderWithCacheStats(shared), nil
|
|
}
|
|
|
|
// OpenTrie opens the main account trie at a specific root hash.
|
|
func (db *CachingDB) OpenTrie(root common.Hash) (Trie, error) {
|
|
if db.triedb.IsVerkle() {
|
|
ts := overlay.LoadTransitionState(db.TrieDB().Disk(), root, db.triedb.IsVerkle())
|
|
if ts.InTransition() {
|
|
panic("transition isn't supported yet")
|
|
}
|
|
if ts.Transitioned() {
|
|
// Use BinaryTrie instead of VerkleTrie when IsVerkle is set
|
|
// (IsVerkle actually means Binary Trie mode in this codebase)
|
|
return bintrie.NewBinaryTrie(root, db.triedb)
|
|
}
|
|
}
|
|
tr, err := trie.NewStateTrie(trie.StateTrieID(root), db.triedb)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return tr, nil
|
|
}
|
|
|
|
// OpenStorageTrie opens the storage trie of an account.
|
|
func (db *CachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, self Trie) (Trie, error) {
|
|
if db.triedb.IsVerkle() {
|
|
return self, nil
|
|
}
|
|
tr, err := trie.NewStateTrie(trie.StorageTrieID(stateRoot, crypto.Keccak256Hash(address.Bytes()), root), db.triedb)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return tr, nil
|
|
}
|
|
|
|
// ContractCodeWithPrefix retrieves a particular contract's code. If the
|
|
// code can't be found in the cache, then check the existence with **new**
|
|
// db scheme.
|
|
func (db *CachingDB) ContractCodeWithPrefix(address common.Address, codeHash common.Hash) []byte {
|
|
code, _ := db.codeCache.Get(codeHash)
|
|
if len(code) > 0 {
|
|
return code
|
|
}
|
|
code = rawdb.ReadCodeWithPrefix(db.disk, codeHash)
|
|
if len(code) > 0 {
|
|
db.codeCache.Add(codeHash, code)
|
|
db.codeSizeCache.Add(codeHash, len(code))
|
|
}
|
|
return code
|
|
}
|
|
|
|
// TrieDB retrieves any intermediate trie-node caching layer.
|
|
func (db *CachingDB) TrieDB() *triedb.Database {
|
|
return db.triedb
|
|
}
|
|
|
|
// PointCache returns the cache of evaluated curve points.
|
|
func (db *CachingDB) PointCache() *utils.PointCache {
|
|
return db.pointCache
|
|
}
|
|
|
|
// Snapshot returns the underlying state snapshot.
|
|
func (db *CachingDB) Snapshot() *snapshot.Tree {
|
|
return db.snap
|
|
}
|
|
|
|
// mustCopyTrie returns a deep-copied trie.
|
|
func mustCopyTrie(t Trie) Trie {
|
|
switch t := t.(type) {
|
|
case *trie.StateTrie:
|
|
return t.Copy()
|
|
case *trie.VerkleTrie:
|
|
return t.Copy()
|
|
case *transitiontrie.TransitionTrie:
|
|
return t.Copy()
|
|
default:
|
|
panic(fmt.Errorf("unknown trie type %T", t))
|
|
}
|
|
}
|