From e2c00d6c96f9c324cc00cd45249416ead0216366 Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Fri, 20 Mar 2026 14:05:01 +0800 Subject: [PATCH] core/state: add hasher interface definition --- core/state/database_hasher.go | 114 ++++++++++++++++++++++++++++++++++ core/state/reader.go | 21 +++++++ 2 files changed, 135 insertions(+) create mode 100644 core/state/database_hasher.go diff --git a/core/state/database_hasher.go b/core/state/database_hasher.go new file mode 100644 index 0000000000..340d3cd523 --- /dev/null +++ b/core/state/database_hasher.go @@ -0,0 +1,114 @@ +// Copyright 2026 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 . + +package state + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/stateless" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/trie/trienode" +) + +// AccountMutation describes a state transition for a single account. +type AccountMutation struct { + Account *Account // Null for deletion + + CodeDirty bool // Flag whether the code is changed + Code []byte // Null for deletion +} + +// Hasher defines the minimal interface for computing state root hashes. +// +// It abstracts over different trie implementations, such as the traditional +// two-layer Merkle Patricia Trie (separate account and storage tries) and a +// unified single-layer binary trie (a single trie covering accounts, storages +// and contract code). +// +// This abstraction also enables alternative implementations, such as a no-op +// hasher for flat-state-only nodes (i.e. nodes that do not store trie data and +// do not perform state validation). +// +// The Hash method may be invoked multiple times and must return a hash that +// reflects all preceding state mutations. This behavior is required for +// compatibility with pre-Byzantium semantics. +type Hasher interface { + // UpdateAccount writes a list of accounts into the state. + UpdateAccount(addresses []common.Address, accounts []AccountMutation) error + + // UpdateStorage writes a list of storage slot value. The hasher handles + // encoding internally. Note, the value with empty data should be + // interpreted as deletion. + UpdateStorage(address common.Address, keys []common.Hash, values []common.Hash) error + + // Hash computes and returns the state root hash without committing. + Hash() common.Hash + + // Commit finalizes all pending changes and returns the resulting state root + // hash, along with the set of dirty trie nodes generated by the updates. + // + // Additionally, if the hasher uses a two-layer structure, the roots of the + // secondary tries together with their original hashes will also be returned + // for all mutated accounts, regardless of whether their storage was modified. + Commit() (common.Hash, *trienode.MergedNodeSet, map[common.Address]common.Hash, map[common.Address]common.Hash, error) + + // Copy returns a deep-copied hasher instance. + Copy() Hasher +} + +// Prefetcher is an optional extension implemented by hashers that can +// asynchronously warm up trie/state data ahead of mutations or hashing. +type Prefetcher interface { + // PrefetchAccount schedules the account for prefetching. + PrefetchAccount(addresses []common.Address) + + // PrefetchStorage schedules the storage slot for prefetching. + PrefetchStorage(addr common.Address, keys []common.Hash) +} + +// WitnessCollector is an optional extension implemented by hashers that can +// construct a stateless witness for the most recent committed state transition. +type WitnessCollector interface { + // Witness returns the stateless witness corresponding to the most recent + // committed state transition. + Witness() (*stateless.Witness, error) +} + +// Prover is an optional extension implemented by hashers that can construct +// proofs against the current state. +type Prover interface { + // ProveAccount constructs a proof for the given account. + // + // The returned proof contains all encoded nodes on the path to the account. + // The account itself is included in the last node and can be retrieved by + // verifying the proof. + // + // If the account does not exist, the returned proof contains all nodes of + // the longest existing prefix of the account key (at least the root), ending + // with the node that proves the absence of the account. + ProveAccount(addr common.Address, proofDb ethdb.KeyValueWriter) error + + // ProveStorage constructs a proof for the given storage slot of the + // specified account. + // + // The returned proof contains all encoded nodes on the path to the storage + // slot. The slot value itself is included in the last node and can be + // retrieved by verifying the proof. + // + // If the account or storage slot does not exist, the returned proof contains + // the nodes required to prove its absence. + ProveStorage(addr common.Address, key common.Hash, proofDb ethdb.KeyValueWriter) error +} diff --git a/core/state/reader.go b/core/state/reader.go index fe0ec71f2d..87eba796a9 100644 --- a/core/state/reader.go +++ b/core/state/reader.go @@ -31,6 +31,7 @@ import ( "github.com/ethereum/go-ethereum/trie/transitiontrie" "github.com/ethereum/go-ethereum/triedb" "github.com/ethereum/go-ethereum/triedb/database" + "github.com/holiman/uint256" ) // ContractCodeReader defines the interface for accessing contract code. @@ -50,6 +51,26 @@ type ContractCodeReader interface { CodeSize(addr common.Address, codeHash common.Hash) int } +// Account represents the metadata of an Ethereum account object. +// Unlike the representation in the Merkle-Patricia Trie, the storage root +// is omitted. This structure is designed to provide a unified view over +// flat state representations and remain compatible with different hashing +// schemes (e.g., a unified binary tree in the future). +type Account struct { + Nonce uint64 + Balance *uint256.Int + CodeHash []byte +} + +// newEmptyAccount returns an empty account. +// nolint:unused +func newEmptyAccount() *Account { + return &Account{ + Balance: uint256.NewInt(0), + CodeHash: types.EmptyCodeHash.Bytes(), + } +} + // StateReader defines the interface for accessing accounts and storage slots // associated with a specific state. //