mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
all: add dbconfig package
This commit is contained in:
parent
ebf9e11af2
commit
c77047a67f
61 changed files with 678 additions and 471 deletions
|
|
@ -36,7 +36,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
"github.com/holiman/uint256"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
|
@ -356,7 +356,10 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||
}
|
||||
|
||||
func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB {
|
||||
sdb := state.NewDatabaseWithConfig(db, &triedb.Config{Preimages: true})
|
||||
config := dbconfig.HashDefaults
|
||||
config.Preimages = true
|
||||
|
||||
sdb := state.NewDatabaseWithConfig(db, &config)
|
||||
statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
|
||||
for addr, a := range accounts {
|
||||
statedb.SetCode(addr, a.Code)
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/internal/flags"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
|
|
@ -148,10 +148,9 @@ func runCmd(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
triedb := triedb.NewDatabase(db, &triedb.Config{
|
||||
Preimages: preimages,
|
||||
HashDB: hashdb.Defaults,
|
||||
})
|
||||
config := dbconfig.HashDefaults
|
||||
config.Preimages = preimages
|
||||
triedb := triedb.NewDatabase(db, &config)
|
||||
defer triedb.Close()
|
||||
genesis := genesisConfig.MustCommit(db, triedb)
|
||||
sdb := state.NewDatabaseWithNodeDB(db, triedb)
|
||||
|
|
|
|||
|
|
@ -428,7 +428,7 @@ func traverseRawState(ctx *cli.Context) error {
|
|||
log.Error("Failed to open iterator", "root", root, "err", err)
|
||||
return err
|
||||
}
|
||||
reader, err := triedb.Reader(root)
|
||||
reader, err := triedb.NodeReader(root)
|
||||
if err != nil {
|
||||
log.Error("State is non-existent", "root", root)
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/p2p/netutil"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
|
|
@ -2193,6 +2194,7 @@ func MakeConsolePreloads(ctx *cli.Context) []string {
|
|||
}
|
||||
|
||||
// MakeTrieDatabase constructs a trie database based on the configured scheme.
|
||||
// Don't forget to call db.Close afterwards to prevent memory leak.
|
||||
func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, readOnly bool, isVerkle bool) *triedb.Database {
|
||||
config := &triedb.Config{
|
||||
Preimages: preimage,
|
||||
|
|
@ -2206,13 +2208,20 @@ func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, read
|
|||
// Read-only mode is not implemented in hash mode,
|
||||
// ignore the parameter silently. TODO(rjl493456442)
|
||||
// please config it if read mode is implemented.
|
||||
config.HashDB = hashdb.Defaults
|
||||
config.HashDB = &hashdb.Config{
|
||||
CleanCacheSize: 16 * 1024 * 1024,
|
||||
ChildResolver: trie.MerkleResolver,
|
||||
}
|
||||
return triedb.NewDatabase(disk, config)
|
||||
}
|
||||
config.PathDB = &pathdb.Config{
|
||||
StateHistory: params.FullImmutabilityThreshold,
|
||||
CleanCacheSize: pathdb.DefaultCleanSize,
|
||||
DirtyCacheSize: pathdb.DefaultBufferSize,
|
||||
TrieOpener: trie.NewMerkleOpener,
|
||||
}
|
||||
if readOnly {
|
||||
config.PathDB = pathdb.ReadOnly
|
||||
} else {
|
||||
config.PathDB = pathdb.Defaults
|
||||
config.PathDB.ReadOnly = true
|
||||
}
|
||||
return triedb.NewDatabase(disk, config)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -171,7 +172,7 @@ func TestHistoryImportAndExport(t *testing.T) {
|
|||
db2.Close()
|
||||
})
|
||||
|
||||
genesis.MustCommit(db2, triedb.NewDatabase(db, triedb.HashDefaults))
|
||||
genesis.MustCommit(db2, triedb.NewDatabase(db, &dbconfig.HashDefaults))
|
||||
imported, err := core.NewBlockChain(db2, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to initialize chain: %v", err)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/metrics"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
|
|
@ -151,6 +152,7 @@ func (c *CacheConfig) triedbConfig() *triedb.Config {
|
|||
if c.StateScheme == rawdb.HashScheme {
|
||||
config.HashDB = &hashdb.Config{
|
||||
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
|
||||
ChildResolver: trie.MerkleResolver,
|
||||
}
|
||||
}
|
||||
if c.StateScheme == rawdb.PathScheme {
|
||||
|
|
@ -158,6 +160,7 @@ func (c *CacheConfig) triedbConfig() *triedb.Config {
|
|||
StateHistory: c.StateHistory,
|
||||
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
|
||||
DirtyCacheSize: c.TrieDirtyLimit * 1024 * 1024,
|
||||
TrieOpener: trie.NewMerkleOpener,
|
||||
}
|
||||
}
|
||||
return config
|
||||
|
|
|
|||
|
|
@ -35,8 +35,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
)
|
||||
|
||||
// rewindTest is a test case for chain rollback upon user request.
|
||||
|
|
@ -2033,13 +2032,13 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
|
|||
}
|
||||
// Reopen the trie database without persisting in-memory dirty nodes.
|
||||
chain.triedb.Close()
|
||||
dbconfig := &triedb.Config{}
|
||||
var dbconf triedb.Config
|
||||
if scheme == rawdb.PathScheme {
|
||||
dbconfig.PathDB = pathdb.Defaults
|
||||
dbconf = dbconfig.PathDefaults
|
||||
} else {
|
||||
dbconfig.HashDB = hashdb.Defaults
|
||||
dbconf = dbconfig.HashDefaults
|
||||
}
|
||||
chain.triedb = triedb.NewDatabase(chain.db, dbconfig)
|
||||
chain.triedb = triedb.NewDatabase(chain.db, &dbconf)
|
||||
chain.stateCache = state.NewDatabaseWithNodeDB(chain.db, chain.triedb)
|
||||
|
||||
// Force run a freeze cycle
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
|
|
@ -362,7 +363,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
|||
}
|
||||
|
||||
// Forcibly use hash-based state scheme for retaining all nodes in disk.
|
||||
triedb := triedb.NewDatabase(db, triedb.HashDefaults)
|
||||
triedb := triedb.NewDatabase(db, &dbconfig.HashDefaults)
|
||||
defer triedb.Close()
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
|
|
@ -407,7 +408,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
|||
// then generate chain on top.
|
||||
func GenerateChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (ethdb.Database, []*types.Block, []types.Receipts) {
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
triedb := triedb.NewDatabase(db, triedb.HashDefaults)
|
||||
triedb := triedb.NewDatabase(db, &dbconfig.HashDefaults)
|
||||
defer triedb.Close()
|
||||
_, err := genesis.Commit(db, triedb)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
)
|
||||
|
||||
func TestGeneratePOSChain(t *testing.T) {
|
||||
|
|
@ -81,7 +82,7 @@ func TestGeneratePOSChain(t *testing.T) {
|
|||
Storage: storage,
|
||||
Code: common.Hex2Bytes("600154600354"),
|
||||
}
|
||||
genesis := gspec.MustCommit(gendb, triedb.NewDatabase(gendb, triedb.HashDefaults))
|
||||
genesis := gspec.MustCommit(gendb, triedb.NewDatabase(gendb, &dbconfig.HashDefaults))
|
||||
|
||||
genchain, genreceipts := GenerateChain(gspec.Config, genesis, beacon.NewFaker(), gendb, 4, func(i int, gen *BlockGen) {
|
||||
gen.SetParentBeaconRoot(common.Hash{byte(i + 1)})
|
||||
|
|
@ -204,7 +205,7 @@ func ExampleGenerateChain() {
|
|||
Config: ¶ms.ChainConfig{HomesteadBlock: new(big.Int)},
|
||||
Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}},
|
||||
}
|
||||
genesis := gspec.MustCommit(genDb, triedb.NewDatabase(genDb, triedb.HashDefaults))
|
||||
genesis := gspec.MustCommit(genDb, triedb.NewDatabase(genDb, &dbconfig.HashDefaults))
|
||||
|
||||
// This call generates a chain of 5 blocks. The function runs for
|
||||
// each block and adds different features to gen based on the
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
|
|
@ -117,16 +117,16 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) {
|
|||
// If a genesis-time verkle trie is requested, create a trie config
|
||||
// with the verkle trie enabled so that the tree can be initialized
|
||||
// as such.
|
||||
var config *triedb.Config
|
||||
var config triedb.Config
|
||||
if isVerkle {
|
||||
config = &triedb.Config{
|
||||
PathDB: pathdb.Defaults,
|
||||
IsVerkle: true,
|
||||
}
|
||||
config = dbconfig.PathDefaults
|
||||
config.IsVerkle = true
|
||||
} else {
|
||||
config = dbconfig.HashDefaults
|
||||
}
|
||||
// Create an ephemeral in-memory database for computing hash,
|
||||
// all the derived states will be discarded to not pollute disk.
|
||||
db := state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), config)
|
||||
db := state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &config)
|
||||
statedb, err := state.New(types.EmptyRootHash, db, nil)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
|
|
|
|||
|
|
@ -32,14 +32,14 @@ import (
|
|||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
)
|
||||
|
||||
func TestInvalidCliqueConfig(t *testing.T) {
|
||||
block := DefaultGoerliGenesisBlock()
|
||||
block.ExtraData = []byte{}
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
if _, err := block.Commit(db, triedb.NewDatabase(db, nil)); err == nil {
|
||||
if _, err := block.Commit(db, triedb.NewDatabase(db, &dbconfig.HashDefaults)); err == nil {
|
||||
t.Fatal("Expected error on invalid clique config")
|
||||
}
|
||||
}
|
||||
|
|
@ -189,7 +189,7 @@ func TestGenesisHashes(t *testing.T) {
|
|||
} {
|
||||
// Test via MustCommit
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
if have := c.genesis.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults)).Hash(); have != c.want {
|
||||
if have := c.genesis.MustCommit(db, triedb.NewDatabase(db, &dbconfig.HashDefaults)).Hash(); have != c.want {
|
||||
t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex())
|
||||
}
|
||||
// Test via ToBlock
|
||||
|
|
@ -207,7 +207,7 @@ func TestGenesis_Commit(t *testing.T) {
|
|||
}
|
||||
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
genesisBlock := genesis.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
|
||||
genesisBlock := genesis.MustCommit(db, triedb.NewDatabase(db, &dbconfig.HashDefaults))
|
||||
|
||||
if genesis.Difficulty != nil {
|
||||
t.Fatalf("assumption wrong")
|
||||
|
|
@ -259,9 +259,9 @@ func TestReadWriteGenesisAlloc(t *testing.T) {
|
|||
|
||||
func newDbConfig(scheme string) *triedb.Config {
|
||||
if scheme == rawdb.HashScheme {
|
||||
return triedb.HashDefaults
|
||||
return &dbconfig.HashDefaults
|
||||
}
|
||||
return &triedb.Config{PathDB: pathdb.Defaults}
|
||||
return &dbconfig.PathDefaults
|
||||
}
|
||||
|
||||
func TestVerkleGenesisCommit(t *testing.T) {
|
||||
|
|
@ -311,7 +311,10 @@ func TestVerkleGenesisCommit(t *testing.T) {
|
|||
}
|
||||
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
triedb := triedb.NewDatabase(db, &triedb.Config{IsVerkle: true, PathDB: pathdb.Defaults})
|
||||
|
||||
config := dbconfig.PathDefaults
|
||||
config.IsVerkle = true
|
||||
triedb := triedb.NewDatabase(db, &config)
|
||||
block := genesis.MustCommit(db, triedb)
|
||||
if !bytes.Equal(block.Root().Bytes(), expected) {
|
||||
t.Fatalf("invalid genesis state root, expected %x, got %x", expected, got)
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
)
|
||||
|
||||
func verifyUnbrokenCanonchain(hc *HeaderChain) error {
|
||||
|
|
@ -73,7 +74,7 @@ func TestHeaderInsertion(t *testing.T) {
|
|||
db = rawdb.NewMemoryDatabase()
|
||||
gspec = &Genesis{BaseFee: big.NewInt(params.InitialBaseFee), Config: params.AllEthashProtocolChanges}
|
||||
)
|
||||
gspec.Commit(db, triedb.NewDatabase(db, nil))
|
||||
gspec.Commit(db, triedb.NewDatabase(db, &dbconfig.HashDefaults))
|
||||
hc, err := NewHeaderChain(db, gspec.Config, ethash.NewFaker(), func() bool { return false })
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"github.com/ethereum/go-ethereum/trie/utils"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -145,7 +146,7 @@ type Trie interface {
|
|||
// concurrent use, but does not retain any recent trie nodes in memory. To keep some
|
||||
// historical state in memory, use the NewDatabaseWithConfig constructor.
|
||||
func NewDatabase(db ethdb.Database) Database {
|
||||
return NewDatabaseWithConfig(db, nil)
|
||||
return NewDatabaseWithConfig(db, &dbconfig.HashDefaults)
|
||||
}
|
||||
|
||||
// NewDatabaseWithConfig creates a backing store for state. The returned database
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -87,7 +88,7 @@ func NewPruner(db ethdb.Database, config Config) (*Pruner, error) {
|
|||
return nil, errors.New("failed to load head block")
|
||||
}
|
||||
// Offline pruning is only supported in legacy hash based scheme.
|
||||
triedb := triedb.NewDatabase(db, triedb.HashDefaults)
|
||||
triedb := triedb.NewDatabase(db, &dbconfig.HashDefaults)
|
||||
|
||||
snapconfig := snapshot.Config{
|
||||
CacheSize: 256,
|
||||
|
|
@ -367,7 +368,7 @@ func RecoverPruning(datadir string, db ethdb.Database) error {
|
|||
AsyncBuild: false,
|
||||
}
|
||||
// Offline pruning is only supported in legacy hash based scheme.
|
||||
triedb := triedb.NewDatabase(db, triedb.HashDefaults)
|
||||
triedb := triedb.NewDatabase(db, &dbconfig.HashDefaults)
|
||||
snaptree, err := snapshot.New(snapconfig, db, triedb, headBlock.Root())
|
||||
if err != nil {
|
||||
return err // The relevant snapshot(s) might not exist
|
||||
|
|
@ -410,7 +411,7 @@ func extractGenesis(db ethdb.Database, stateBloom *stateBloom) error {
|
|||
if genesis == nil {
|
||||
return errors.New("missing genesis block")
|
||||
}
|
||||
t, err := trie.NewStateTrie(trie.StateTrieID(genesis.Root()), triedb.NewDatabase(db, triedb.HashDefaults))
|
||||
t, err := trie.NewStateTrie(trie.StateTrieID(genesis.Root()), triedb.NewDatabase(db, &dbconfig.HashDefaults))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -434,7 +435,7 @@ func extractGenesis(db ethdb.Database, stateBloom *stateBloom) error {
|
|||
}
|
||||
if acc.Root != types.EmptyRootHash {
|
||||
id := trie.StorageTrieID(genesis.Root(), common.BytesToHash(accIter.LeafKey()), acc.Root)
|
||||
storageTrie, err := trie.NewStateTrie(id, triedb.NewDatabase(db, triedb.HashDefaults))
|
||||
storageTrie, err := trie.NewStateTrie(id, triedb.NewDatabase(db, &dbconfig.HashDefaults))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -354,7 +355,7 @@ func (dl *diskLayer) generateRange(ctx *generatorContext, trieId *trie.ID, prefi
|
|||
var resolver trie.NodeResolver
|
||||
if len(result.keys) > 0 {
|
||||
mdb := rawdb.NewMemoryDatabase()
|
||||
tdb := triedb.NewDatabase(mdb, triedb.HashDefaults)
|
||||
tdb := triedb.NewDatabase(mdb, &dbconfig.HashDefaults)
|
||||
defer tdb.Close()
|
||||
snapTrie := trie.NewEmpty(tdb)
|
||||
for i, key := range result.keys {
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
"github.com/holiman/uint256"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
|
@ -162,14 +161,14 @@ type testHelper struct {
|
|||
}
|
||||
|
||||
func newHelper(scheme string) *testHelper {
|
||||
diskdb := rawdb.NewMemoryDatabase()
|
||||
config := &triedb.Config{}
|
||||
var config triedb.Config
|
||||
if scheme == rawdb.PathScheme {
|
||||
config.PathDB = &pathdb.Config{} // disable caching
|
||||
config = dbconfig.PathDefaults
|
||||
} else {
|
||||
config.HashDB = &hashdb.Config{} // disable caching
|
||||
config = dbconfig.HashDefaults
|
||||
}
|
||||
triedb := triedb.NewDatabase(diskdb, config)
|
||||
diskdb := rawdb.NewMemoryDatabase()
|
||||
triedb := triedb.NewDatabase(diskdb, &config)
|
||||
accTrie, _ := trie.NewStateTrie(trie.StateTrieID(types.EmptyRootHash), triedb)
|
||||
return &testHelper{
|
||||
diskdb: diskdb,
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
|
|
@ -43,7 +43,9 @@ func newStateEnv() *stateEnv {
|
|||
|
||||
func TestDump(t *testing.T) {
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
tdb := NewDatabaseWithConfig(db, &triedb.Config{Preimages: true})
|
||||
config := dbconfig.HashDefaults
|
||||
config.Preimages = true
|
||||
tdb := NewDatabaseWithConfig(db, &config)
|
||||
sdb, _ := New(types.EmptyRootHash, tdb, nil)
|
||||
s := &stateEnv{db: db, state: sdb}
|
||||
|
||||
|
|
@ -100,7 +102,9 @@ func TestDump(t *testing.T) {
|
|||
|
||||
func TestIterativeDump(t *testing.T) {
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
tdb := NewDatabaseWithConfig(db, &triedb.Config{Preimages: true})
|
||||
config := dbconfig.HashDefaults
|
||||
config.Preimages = true
|
||||
tdb := NewDatabaseWithConfig(db, &config)
|
||||
sdb, _ := New(types.EmptyRootHash, tdb, nil)
|
||||
s := &stateEnv{db: db, state: sdb}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"github.com/ethereum/go-ethereum/trie/triestate"
|
||||
"github.com/ethereum/go-ethereum/triedb/state"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
|
|
@ -130,7 +130,7 @@ type StateDB struct {
|
|||
StorageDeleted int
|
||||
|
||||
// Testing hooks
|
||||
onCommit func(states *triestate.Set) // Hook invoked when commit is performed
|
||||
onCommit func(states *state.Origin) // Hook invoked when commit is performed
|
||||
}
|
||||
|
||||
// New creates a new state from a given trie.
|
||||
|
|
@ -1239,7 +1239,7 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
|
|||
}
|
||||
if root != origin {
|
||||
start = time.Now()
|
||||
set := triestate.New(s.accountsOrigin, s.storagesOrigin)
|
||||
set := state.NewOrigin(s.accountsOrigin, s.storagesOrigin)
|
||||
if err := s.db.TrieDB().Update(root, origin, block, nodes, set); err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ import (
|
|||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/triestate"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
"github.com/ethereum/go-ethereum/triedb/state"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
|
|
@ -177,12 +177,12 @@ func (test *stateTest) run() bool {
|
|||
roots []common.Hash
|
||||
accountList []map[common.Address][]byte
|
||||
storageList []map[common.Address]map[common.Hash][]byte
|
||||
onCommit = func(states *triestate.Set) {
|
||||
onCommit = func(states *state.Origin) {
|
||||
accountList = append(accountList, copySet(states.Accounts))
|
||||
storageList = append(storageList, copy2DSet(states.Storages))
|
||||
}
|
||||
disk = rawdb.NewMemoryDatabase()
|
||||
tdb = triedb.NewDatabase(disk, &triedb.Config{PathDB: pathdb.Defaults})
|
||||
tdb = triedb.NewDatabase(disk, &dbconfig.PathDefaults)
|
||||
sdb = NewDatabaseWithNodeDB(disk, tdb)
|
||||
byzantium = rand.Intn(2) == 0
|
||||
)
|
||||
|
|
|
|||
|
|
@ -38,8 +38,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
|
|
@ -49,7 +48,7 @@ func TestUpdateLeaks(t *testing.T) {
|
|||
// Create an empty state database
|
||||
var (
|
||||
db = rawdb.NewMemoryDatabase()
|
||||
tdb = triedb.NewDatabase(db, nil)
|
||||
tdb = triedb.NewDatabase(db, &dbconfig.HashDefaults)
|
||||
)
|
||||
state, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(db, tdb), nil)
|
||||
|
||||
|
|
@ -85,8 +84,8 @@ func TestIntermediateLeaks(t *testing.T) {
|
|||
// Create two state databases, one transitioning to the final state, the other final from the beginning
|
||||
transDb := rawdb.NewMemoryDatabase()
|
||||
finalDb := rawdb.NewMemoryDatabase()
|
||||
transNdb := triedb.NewDatabase(transDb, nil)
|
||||
finalNdb := triedb.NewDatabase(finalDb, nil)
|
||||
transNdb := triedb.NewDatabase(transDb, &dbconfig.HashDefaults)
|
||||
finalNdb := triedb.NewDatabase(finalDb, &dbconfig.HashDefaults)
|
||||
transState, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(transDb, transNdb), nil)
|
||||
finalState, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(finalDb, finalNdb), nil)
|
||||
|
||||
|
|
@ -803,14 +802,9 @@ func testMissingTrieNodes(t *testing.T, scheme string) {
|
|||
memDb = rawdb.NewMemoryDatabase()
|
||||
)
|
||||
if scheme == rawdb.PathScheme {
|
||||
tdb = triedb.NewDatabase(memDb, &triedb.Config{PathDB: &pathdb.Config{
|
||||
CleanCacheSize: 0,
|
||||
DirtyCacheSize: 0,
|
||||
}}) // disable caching
|
||||
tdb = triedb.NewDatabase(memDb, &dbconfig.PathDefaults) // disable caching
|
||||
} else {
|
||||
tdb = triedb.NewDatabase(memDb, &triedb.Config{HashDB: &hashdb.Config{
|
||||
CleanCacheSize: 0,
|
||||
}}) // disable caching
|
||||
tdb = triedb.NewDatabase(memDb, &dbconfig.HashDefaults) // cache is disabled by default
|
||||
}
|
||||
db := NewDatabaseWithNodeDB(memDb, tdb)
|
||||
|
||||
|
|
@ -1033,7 +1027,7 @@ func TestFlushOrderDataLoss(t *testing.T) {
|
|||
// Create a state trie with many accounts and slots
|
||||
var (
|
||||
memdb = rawdb.NewMemoryDatabase()
|
||||
triedb = triedb.NewDatabase(memdb, nil)
|
||||
triedb = triedb.NewDatabase(memdb, &dbconfig.HashDefaults)
|
||||
statedb = NewDatabaseWithNodeDB(memdb, triedb)
|
||||
state, _ = New(types.EmptyRootHash, statedb, nil)
|
||||
)
|
||||
|
|
@ -1105,7 +1099,7 @@ func TestStateDBTransientStorage(t *testing.T) {
|
|||
func TestResetObject(t *testing.T) {
|
||||
var (
|
||||
disk = rawdb.NewMemoryDatabase()
|
||||
tdb = triedb.NewDatabase(disk, nil)
|
||||
tdb = triedb.NewDatabase(disk, &dbconfig.HashDefaults)
|
||||
db = NewDatabaseWithNodeDB(disk, tdb)
|
||||
snaps, _ = snapshot.New(snapshot.Config{CacheSize: 10}, disk, tdb, types.EmptyRootHash)
|
||||
state, _ = New(types.EmptyRootHash, db, snaps)
|
||||
|
|
@ -1139,7 +1133,7 @@ func TestResetObject(t *testing.T) {
|
|||
func TestDeleteStorage(t *testing.T) {
|
||||
var (
|
||||
disk = rawdb.NewMemoryDatabase()
|
||||
tdb = triedb.NewDatabase(disk, nil)
|
||||
tdb = triedb.NewDatabase(disk, &dbconfig.HashDefaults)
|
||||
db = NewDatabaseWithNodeDB(disk, tdb)
|
||||
snaps, _ = snapshot.New(snapshot.Config{CacheSize: 10}, disk, tdb, types.EmptyRootHash)
|
||||
state, _ = New(types.EmptyRootHash, db, snaps)
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
|
|
@ -44,14 +43,16 @@ type testAccount struct {
|
|||
// makeTestState create a sample test state to test node-wise reconstruction.
|
||||
func makeTestState(scheme string) (ethdb.Database, Database, *triedb.Database, common.Hash, []*testAccount) {
|
||||
// Create an empty state
|
||||
config := &triedb.Config{Preimages: true}
|
||||
var config triedb.Config
|
||||
if scheme == rawdb.PathScheme {
|
||||
config.PathDB = pathdb.Defaults
|
||||
config = dbconfig.PathDefaults
|
||||
} else {
|
||||
config.HashDB = hashdb.Defaults
|
||||
config = dbconfig.HashDefaults
|
||||
}
|
||||
config.Preimages = true
|
||||
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
nodeDb := triedb.NewDatabase(db, config)
|
||||
nodeDb := triedb.NewDatabase(db, &config)
|
||||
sdb := NewDatabaseWithNodeDB(db, nodeDb)
|
||||
state, _ := New(types.EmptyRootHash, sdb, nil)
|
||||
|
||||
|
|
@ -90,7 +91,9 @@ func makeTestState(scheme string) (ethdb.Database, Database, *triedb.Database, c
|
|||
func checkStateAccounts(t *testing.T, db ethdb.Database, scheme string, root common.Hash, accounts []*testAccount) {
|
||||
var config triedb.Config
|
||||
if scheme == rawdb.PathScheme {
|
||||
config.PathDB = pathdb.Defaults
|
||||
config = dbconfig.PathDefaults
|
||||
} else {
|
||||
config = dbconfig.HashDefaults
|
||||
}
|
||||
// Check root availability and state contents
|
||||
state, err := New(root, NewDatabaseWithConfig(db, &config), nil)
|
||||
|
|
@ -115,11 +118,15 @@ func checkStateAccounts(t *testing.T, db ethdb.Database, scheme string, root com
|
|||
|
||||
// checkStateConsistency checks that all data of a state root is present.
|
||||
func checkStateConsistency(db ethdb.Database, scheme string, root common.Hash) error {
|
||||
config := &triedb.Config{Preimages: true}
|
||||
var config triedb.Config
|
||||
if scheme == rawdb.PathScheme {
|
||||
config.PathDB = pathdb.Defaults
|
||||
config = dbconfig.PathDefaults
|
||||
} else {
|
||||
config = dbconfig.HashDefaults
|
||||
}
|
||||
state, err := New(root, NewDatabaseWithConfig(db, config), nil)
|
||||
config.Preimages = true
|
||||
|
||||
state, err := New(root, NewDatabaseWithConfig(db, &config), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -131,8 +138,8 @@ func checkStateConsistency(db ethdb.Database, scheme string, root common.Hash) e
|
|||
|
||||
// Tests that an empty state is not scheduled for syncing.
|
||||
func TestEmptyStateSync(t *testing.T) {
|
||||
dbA := triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil)
|
||||
dbB := triedb.NewDatabase(rawdb.NewMemoryDatabase(), &triedb.Config{PathDB: pathdb.Defaults})
|
||||
dbA := triedb.NewDatabase(rawdb.NewMemoryDatabase(), &dbconfig.HashDefaults)
|
||||
dbB := triedb.NewDatabase(rawdb.NewMemoryDatabase(), &dbconfig.PathDefaults)
|
||||
|
||||
sync := NewStateSync(types.EmptyRootHash, rawdb.NewMemoryDatabase(), nil, dbA.Scheme())
|
||||
if paths, nodes, codes := sync.Missing(1); len(paths) != 0 || len(nodes) != 0 || len(codes) != 0 {
|
||||
|
|
@ -206,7 +213,7 @@ func testIterativeStateSync(t *testing.T, count int, commit bool, bypath bool, s
|
|||
for i := 0; i < len(codes); i++ {
|
||||
codeElements = append(codeElements, stateElement{code: codes[i]})
|
||||
}
|
||||
reader, err := ndb.Reader(srcRoot)
|
||||
reader, err := ndb.NodeReader(srcRoot)
|
||||
if err != nil {
|
||||
t.Fatalf("state is not existent, %#x", srcRoot)
|
||||
}
|
||||
|
|
@ -325,7 +332,7 @@ func testIterativeDelayedStateSync(t *testing.T, scheme string) {
|
|||
for i := 0; i < len(codes); i++ {
|
||||
codeElements = append(codeElements, stateElement{code: codes[i]})
|
||||
}
|
||||
reader, err := ndb.Reader(srcRoot)
|
||||
reader, err := ndb.NodeReader(srcRoot)
|
||||
if err != nil {
|
||||
t.Fatalf("state is not existent, %#x", srcRoot)
|
||||
}
|
||||
|
|
@ -429,7 +436,7 @@ func testIterativeRandomStateSync(t *testing.T, count int, scheme string) {
|
|||
for _, hash := range codes {
|
||||
codeQueue[hash] = struct{}{}
|
||||
}
|
||||
reader, err := ndb.Reader(srcRoot)
|
||||
reader, err := ndb.NodeReader(srcRoot)
|
||||
if err != nil {
|
||||
t.Fatalf("state is not existent, %#x", srcRoot)
|
||||
}
|
||||
|
|
@ -522,7 +529,7 @@ func testIterativeRandomDelayedStateSync(t *testing.T, scheme string) {
|
|||
for _, hash := range codes {
|
||||
codeQueue[hash] = struct{}{}
|
||||
}
|
||||
reader, err := ndb.Reader(srcRoot)
|
||||
reader, err := ndb.NodeReader(srcRoot)
|
||||
if err != nil {
|
||||
t.Fatalf("state is not existent, %#x", srcRoot)
|
||||
}
|
||||
|
|
@ -627,7 +634,7 @@ func testIncompleteStateSync(t *testing.T, scheme string) {
|
|||
addedPaths []string
|
||||
addedHashes []common.Hash
|
||||
)
|
||||
reader, err := ndb.Reader(srcRoot)
|
||||
reader, err := ndb.NodeReader(srcRoot)
|
||||
if err != nil {
|
||||
t.Fatalf("state is not available %x", srcRoot)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
)
|
||||
|
||||
func TestDeriveSha(t *testing.T) {
|
||||
|
|
@ -40,7 +41,7 @@ func TestDeriveSha(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
for len(txs) < 1000 {
|
||||
exp := types.DeriveSha(txs, trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil)))
|
||||
exp := types.DeriveSha(txs, trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), &dbconfig.HashDefaults)))
|
||||
got := types.DeriveSha(txs, trie.NewStackTrie(nil))
|
||||
if !bytes.Equal(got[:], exp[:]) {
|
||||
t.Fatalf("%d txs: got %x exp %x", len(txs), got, exp)
|
||||
|
|
@ -87,7 +88,7 @@ func BenchmarkDeriveSha200(b *testing.B) {
|
|||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
exp = types.DeriveSha(txs, trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil)))
|
||||
exp = types.DeriveSha(txs, trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), &dbconfig.HashDefaults)))
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -108,7 +109,7 @@ func TestFuzzDeriveSha(t *testing.T) {
|
|||
rndSeed := mrand.Int()
|
||||
for i := 0; i < 10; i++ {
|
||||
seed := rndSeed + i
|
||||
exp := types.DeriveSha(newDummy(i), trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil)))
|
||||
exp := types.DeriveSha(newDummy(i), trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), &dbconfig.HashDefaults)))
|
||||
got := types.DeriveSha(newDummy(i), trie.NewStackTrie(nil))
|
||||
if !bytes.Equal(got[:], exp[:]) {
|
||||
printList(newDummy(seed))
|
||||
|
|
@ -136,7 +137,7 @@ func TestDerivableList(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for i, tc := range tcs[1:] {
|
||||
exp := types.DeriveSha(flatList(tc), trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil)))
|
||||
exp := types.DeriveSha(flatList(tc), trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), &dbconfig.HashDefaults)))
|
||||
got := types.DeriveSha(flatList(tc), trie.NewStackTrie(nil))
|
||||
if !bytes.Equal(got[:], exp[:]) {
|
||||
t.Fatalf("case %d: got %x exp %x", i, got, exp)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
"github.com/holiman/uint256"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
|
@ -62,13 +62,15 @@ func accountRangeTest(t *testing.T, trie *state.Trie, statedb *state.StateDB, st
|
|||
func TestAccountRange(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
config := dbconfig.HashDefaults
|
||||
config.Preimages = true
|
||||
|
||||
var (
|
||||
statedb = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &triedb.Config{Preimages: true})
|
||||
statedb = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &config)
|
||||
sdb, _ = state.New(types.EmptyRootHash, statedb, nil)
|
||||
addrs = [AccountRangeMaxResults * 2]common.Address{}
|
||||
m = map[common.Address]bool{}
|
||||
)
|
||||
|
||||
for i := range addrs {
|
||||
hash := common.HexToHash(fmt.Sprintf("%x", i))
|
||||
addr := common.BytesToAddress(crypto.Keccak256Hash(hash.Bytes()).Bytes())
|
||||
|
|
@ -158,9 +160,12 @@ func TestEmptyAccountRange(t *testing.T) {
|
|||
func TestStorageRangeAt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
config := dbconfig.HashDefaults
|
||||
config.Preimages = true
|
||||
|
||||
// Create a state where account 0x010000... has a few storage entries.
|
||||
var (
|
||||
db = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &triedb.Config{Preimages: true})
|
||||
db = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &config)
|
||||
sdb, _ = state.New(types.EmptyRootHash, db, nil)
|
||||
addr = common.Address{0x01}
|
||||
keys = []common.Hash{ // hashes of Keys of storage
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
)
|
||||
|
||||
// Test chain parameters.
|
||||
|
|
@ -44,7 +45,7 @@ var (
|
|||
Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
|
||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||
}
|
||||
testGenesis = testGspec.MustCommit(testDB, triedb.NewDatabase(testDB, triedb.HashDefaults))
|
||||
testGenesis = testGspec.MustCommit(testDB, triedb.NewDatabase(testDB, &dbconfig.HashDefaults))
|
||||
)
|
||||
|
||||
// The common prefix of all test chains:
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
)
|
||||
|
||||
func makeReceipt(addr common.Address) *types.Receipt {
|
||||
|
|
@ -86,7 +87,7 @@ func BenchmarkFilters(b *testing.B) {
|
|||
// The test txs are not properly signed, can't simply create a chain
|
||||
// and then import blocks. TODO(rjl493456442) try to get rid of the
|
||||
// manual database writes.
|
||||
gspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
|
||||
gspec.MustCommit(db, triedb.NewDatabase(db, &dbconfig.HashDefaults))
|
||||
|
||||
for i, block := range chain {
|
||||
rawdb.WriteBlock(db, block)
|
||||
|
|
@ -181,7 +182,7 @@ func TestFilters(t *testing.T) {
|
|||
|
||||
// Hack: GenerateChainWithGenesis creates a new db.
|
||||
// Commit the genesis manually and use GenerateChain.
|
||||
_, err = gspec.Commit(db, triedb.NewDatabase(db, nil))
|
||||
_, err = gspec.Commit(db, triedb.NewDatabase(db, &dbconfig.HashDefaults))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -166,7 +166,10 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBacke
|
|||
b.AddTx(types.MustSignNewTx(key, signer, txdata))
|
||||
})
|
||||
// Construct testing chain
|
||||
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), &core.CacheConfig{TrieCleanNoPrefetch: true}, gspec, nil, engine, vm.Config{}, nil, nil)
|
||||
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), &core.CacheConfig{
|
||||
TrieCleanNoPrefetch: true,
|
||||
StateScheme: rawdb.HashScheme,
|
||||
}, gspec, nil, engine, vm.Config{}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create local chain, %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,13 +32,13 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/internal/testrand"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/testutil"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
"github.com/holiman/uint256"
|
||||
"golang.org/x/crypto/sha3"
|
||||
"golang.org/x/exp/slices"
|
||||
|
|
@ -1816,8 +1816,8 @@ func makeUnevenStorageTrie(owner common.Hash, slots int, db *triedb.Database) (c
|
|||
break
|
||||
}
|
||||
for j := 0; j < slots/3; j++ {
|
||||
key := append([]byte{byte(n)}, testutil.RandBytes(31)...)
|
||||
val, _ := rlp.EncodeToBytes(testutil.RandBytes(32))
|
||||
key := append([]byte{byte(n)}, testrand.Bytes(31)...)
|
||||
val, _ := rlp.EncodeToBytes(testrand.Bytes(32))
|
||||
|
||||
elem := &kv{key, val}
|
||||
tr.MustUpdate(elem.k, elem.v)
|
||||
|
|
@ -1970,7 +1970,7 @@ func TestSlotEstimation(t *testing.T) {
|
|||
|
||||
func newDbConfig(scheme string) *triedb.Config {
|
||||
if scheme == rawdb.HashScheme {
|
||||
return &triedb.Config{}
|
||||
return &dbconfig.HashDefaults
|
||||
}
|
||||
return &triedb.Config{PathDB: pathdb.Defaults}
|
||||
return &dbconfig.PathDefaults
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
)
|
||||
|
||||
// noopReleaser is returned in case there is no operation expected
|
||||
|
|
@ -68,7 +69,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
|
|||
// the internal junks created by tracing will be persisted into the disk.
|
||||
// TODO(rjl493456442), clean cache is disabled to prevent memory leak,
|
||||
// please re-enable it for better performance.
|
||||
database = state.NewDatabaseWithConfig(eth.chainDb, triedb.HashDefaults)
|
||||
database = state.NewDatabaseWithConfig(eth.chainDb, &dbconfig.HashDefaults)
|
||||
if statedb, err = state.New(block.Root(), database, nil); err == nil {
|
||||
log.Info("Found disk backend for state trie", "root", block.Root(), "number", block.Number())
|
||||
return statedb, noopReleaser, nil
|
||||
|
|
@ -85,7 +86,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
|
|||
// the internal junks created by tracing will be persisted into the disk.
|
||||
// TODO(rjl493456442), clean cache is disabled to prevent memory leak,
|
||||
// please re-enable it for better performance.
|
||||
tdb = triedb.NewDatabase(eth.chainDb, triedb.HashDefaults)
|
||||
tdb = triedb.NewDatabase(eth.chainDb, &dbconfig.HashDefaults)
|
||||
database = state.NewDatabaseWithNodeDB(eth.chainDb, tdb)
|
||||
|
||||
// If we didn't check the live database, do check state over ephemeral database,
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ func newTestBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i i
|
|||
TrieDirtyLimit: 256,
|
||||
TrieTimeLimit: 5 * time.Minute,
|
||||
SnapshotLimit: 0,
|
||||
StateScheme: rawdb.HashScheme,
|
||||
TrieDirtyDisabled: true, // Archive mode
|
||||
}
|
||||
chain, err := core.NewBlockChain(backend.chaindb, cacheConfig, gspec, nil, backend.engine, vm.Config{}, nil, nil)
|
||||
|
|
|
|||
|
|
@ -441,6 +441,7 @@ func newTestBackend(t *testing.T, n int, gspec *core.Genesis, engine consensus.E
|
|||
TrieTimeLimit: 5 * time.Minute,
|
||||
SnapshotLimit: 0,
|
||||
TrieDirtyDisabled: true, // Archive mode
|
||||
StateScheme: rawdb.HashScheme,
|
||||
}
|
||||
)
|
||||
accman, acc := newTestAccountManager(t)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
// 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 testutil
|
||||
package testrand
|
||||
|
||||
import (
|
||||
crand "crypto/rand"
|
||||
|
|
@ -22,11 +22,9 @@ import (
|
|||
mrand "math/rand"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
)
|
||||
|
||||
// Prng is a pseudo random number generator seeded by strong randomness.
|
||||
// prng is a pseudo random number generator seeded by strong randomness.
|
||||
// The randomness is printed on startup in order to make failures reproducible.
|
||||
var prng = initRand()
|
||||
|
||||
|
|
@ -37,25 +35,19 @@ func initRand() *mrand.Rand {
|
|||
return rnd
|
||||
}
|
||||
|
||||
// RandBytes generates a random byte slice with specified length.
|
||||
func RandBytes(n int) []byte {
|
||||
// Bytes generates a random byte slice with specified length.
|
||||
func Bytes(n int) []byte {
|
||||
r := make([]byte, n)
|
||||
prng.Read(r)
|
||||
return r
|
||||
}
|
||||
|
||||
// RandomHash generates a random blob of data and returns it as a hash.
|
||||
func RandomHash() common.Hash {
|
||||
return common.BytesToHash(RandBytes(common.HashLength))
|
||||
// Hash generates a random hash.
|
||||
func Hash() common.Hash {
|
||||
return common.BytesToHash(Bytes(common.HashLength))
|
||||
}
|
||||
|
||||
// RandomAddress generates a random blob of data and returns it as an address.
|
||||
func RandomAddress() common.Address {
|
||||
return common.BytesToAddress(RandBytes(common.AddressLength))
|
||||
}
|
||||
|
||||
// RandomNode generates a random node.
|
||||
func RandomNode() *trienode.Node {
|
||||
val := RandBytes(100)
|
||||
return trienode.New(crypto.Keccak256Hash(val), val)
|
||||
// Address generates a random address.
|
||||
func Address() common.Address {
|
||||
return common.BytesToAddress(Bytes(common.AddressLength))
|
||||
}
|
||||
|
|
@ -36,6 +36,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
)
|
||||
|
||||
type mockBackend struct {
|
||||
|
|
@ -143,7 +144,7 @@ func createMiner(t *testing.T) *Miner {
|
|||
}
|
||||
// Create chainConfig
|
||||
chainDB := rawdb.NewMemoryDatabase()
|
||||
triedb := triedb.NewDatabase(chainDB, nil)
|
||||
triedb := triedb.NewDatabase(chainDB, &dbconfig.HashDefaults)
|
||||
genesis := minerTestGenesisBlock(15, 11_500_000, common.HexToAddress("12345"))
|
||||
chainConfig, _, err := core.SetupGenesisBlock(chainDB, triedb, genesis)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -40,8 +40,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
)
|
||||
|
||||
// A BlockTest checks handling of entire blocks.
|
||||
|
|
@ -117,18 +116,18 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, tracer vm.EVMLogger, po
|
|||
// import pre accounts & construct test genesis block & state root
|
||||
var (
|
||||
db = rawdb.NewMemoryDatabase()
|
||||
tconf = &triedb.Config{
|
||||
Preimages: true,
|
||||
}
|
||||
dbconf triedb.Config
|
||||
)
|
||||
if scheme == rawdb.PathScheme {
|
||||
tconf.PathDB = pathdb.Defaults
|
||||
dbconf = dbconfig.PathDefaults
|
||||
} else {
|
||||
tconf.HashDB = hashdb.Defaults
|
||||
dbconf = dbconfig.HashDefaults
|
||||
}
|
||||
dbconf.Preimages = true
|
||||
|
||||
// Commit genesis state
|
||||
gspec := t.genesis(config)
|
||||
triedb := triedb.NewDatabase(db, tconf)
|
||||
triedb := triedb.NewDatabase(db, &dbconf)
|
||||
gblock, err := gspec.Commit(db, triedb)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/ethdb/memorydb"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
|
|
@ -57,7 +58,7 @@ func (f *fuzzer) readInt() uint64 {
|
|||
}
|
||||
|
||||
func (f *fuzzer) randomTrie(n int) (*trie.Trie, map[string]*kv) {
|
||||
trie := trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil))
|
||||
trie := trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), &dbconfig.HashDefaults))
|
||||
vals := make(map[string]*kv)
|
||||
size := f.readInt()
|
||||
// Fill it with some fluff
|
||||
|
|
|
|||
|
|
@ -40,8 +40,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/dbconfig"
|
||||
"github.com/holiman/uint256"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
|
@ -444,13 +443,15 @@ type StateTestState struct {
|
|||
|
||||
// MakePreState creates a state containing the given allocation.
|
||||
func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, snapshotter bool, scheme string) StateTestState {
|
||||
tconf := &triedb.Config{Preimages: true}
|
||||
var dbconf triedb.Config
|
||||
if scheme == rawdb.HashScheme {
|
||||
tconf.HashDB = hashdb.Defaults
|
||||
dbconf = dbconfig.HashDefaults
|
||||
} else {
|
||||
tconf.PathDB = pathdb.Defaults
|
||||
dbconf = dbconfig.PathDefaults
|
||||
}
|
||||
triedb := triedb.NewDatabase(db, tconf)
|
||||
dbconf.Preimages = true
|
||||
|
||||
triedb := triedb.NewDatabase(db, &dbconf)
|
||||
sdb := state.NewDatabaseWithNodeDB(db, triedb)
|
||||
statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
|
||||
for addr, a := range accounts {
|
||||
|
|
|
|||
|
|
@ -154,12 +154,8 @@ func (c *committer) store(path []byte, n node) node {
|
|||
return hash
|
||||
}
|
||||
|
||||
// MerkleResolver the children resolver in merkle-patricia-tree.
|
||||
type MerkleResolver struct{}
|
||||
|
||||
// ForEach implements childResolver, decodes the provided node and
|
||||
// traverses the children inside.
|
||||
func (resolver MerkleResolver) ForEach(node []byte, onChild func(common.Hash)) {
|
||||
// MerkleResolver decodes the provided node and traverses the children inside.
|
||||
func MerkleResolver(node []byte, onChild func(common.Hash)) {
|
||||
forGatherChildren(mustDecodeNodeUnsafe(nil, node), onChild)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/triedb/database"
|
||||
)
|
||||
|
||||
// testReader implements database.Reader interface, providing function to
|
||||
// testReader implements database.NodeReader interface, providing function to
|
||||
// access trie nodes.
|
||||
type testReader struct {
|
||||
db ethdb.Database
|
||||
|
|
@ -33,7 +33,7 @@ type testReader struct {
|
|||
nodes []*trienode.MergedNodeSet // sorted from new to old
|
||||
}
|
||||
|
||||
// Node implements database.Reader interface, retrieving trie node with
|
||||
// Node implements database.NodeReader interface, retrieving trie node with
|
||||
// all available cached layers.
|
||||
func (r *testReader) Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, error) {
|
||||
// Check the node presence with the cached layer, from latest to oldest.
|
||||
|
|
@ -73,7 +73,7 @@ func newTestDatabase(diskdb ethdb.Database, scheme string) *testDb {
|
|||
}
|
||||
}
|
||||
|
||||
func (db *testDb) Reader(stateRoot common.Hash) (database.Reader, error) {
|
||||
func (db *testDb) NodeReader(stateRoot common.Hash) (database.NodeReader, error) {
|
||||
nodes, _ := db.dirties(stateRoot, true)
|
||||
return &testReader{db: db.disk, scheme: db.scheme, nodes: nodes}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ func testNodeIteratorCoverage(t *testing.T, scheme string) {
|
|||
}
|
||||
}
|
||||
// Cross check the hashes and the database itself
|
||||
reader, err := nodeDb.Reader(trie.Hash())
|
||||
reader, err := nodeDb.NodeReader(trie.Hash())
|
||||
if err != nil {
|
||||
t.Fatalf("state is not available %x", trie.Hash())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/trie/testutil"
|
||||
"github.com/ethereum/go-ethereum/internal/testrand"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
|
@ -431,12 +431,12 @@ func TestPartialStackTrie(t *testing.T) {
|
|||
for i := 0; i < n; i++ {
|
||||
var val []byte
|
||||
if rand.Intn(3) == 0 {
|
||||
val = testutil.RandBytes(3)
|
||||
val = testrand.Bytes(3)
|
||||
} else {
|
||||
val = testutil.RandBytes(32)
|
||||
val = testrand.Bytes(32)
|
||||
}
|
||||
entries = append(entries, &kv{
|
||||
k: testutil.RandBytes(32),
|
||||
k: testrand.Bytes(32),
|
||||
v: val,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ func testIterativeSync(t *testing.T, count int, bypath bool, scheme string) {
|
|||
syncPath: NewSyncPath([]byte(paths[i])),
|
||||
})
|
||||
}
|
||||
reader, err := srcDb.Reader(srcTrie.Hash())
|
||||
reader, err := srcDb.NodeReader(srcTrie.Hash())
|
||||
if err != nil {
|
||||
t.Fatalf("State is not available %x", srcTrie.Hash())
|
||||
}
|
||||
|
|
@ -257,7 +257,7 @@ func testIterativeDelayedSync(t *testing.T, scheme string) {
|
|||
syncPath: NewSyncPath([]byte(paths[i])),
|
||||
})
|
||||
}
|
||||
reader, err := srcDb.Reader(srcTrie.Hash())
|
||||
reader, err := srcDb.NodeReader(srcTrie.Hash())
|
||||
if err != nil {
|
||||
t.Fatalf("State is not available %x", srcTrie.Hash())
|
||||
}
|
||||
|
|
@ -326,7 +326,7 @@ func testIterativeRandomSync(t *testing.T, count int, scheme string) {
|
|||
syncPath: NewSyncPath([]byte(paths[i])),
|
||||
}
|
||||
}
|
||||
reader, err := srcDb.Reader(srcTrie.Hash())
|
||||
reader, err := srcDb.NodeReader(srcTrie.Hash())
|
||||
if err != nil {
|
||||
t.Fatalf("State is not available %x", srcTrie.Hash())
|
||||
}
|
||||
|
|
@ -393,7 +393,7 @@ func testIterativeRandomDelayedSync(t *testing.T, scheme string) {
|
|||
syncPath: NewSyncPath([]byte(path)),
|
||||
}
|
||||
}
|
||||
reader, err := srcDb.Reader(srcTrie.Hash())
|
||||
reader, err := srcDb.NodeReader(srcTrie.Hash())
|
||||
if err != nil {
|
||||
t.Fatalf("State is not available %x", srcTrie.Hash())
|
||||
}
|
||||
|
|
@ -465,7 +465,7 @@ func testDuplicateAvoidanceSync(t *testing.T, scheme string) {
|
|||
syncPath: NewSyncPath([]byte(paths[i])),
|
||||
})
|
||||
}
|
||||
reader, err := srcDb.Reader(srcTrie.Hash())
|
||||
reader, err := srcDb.NodeReader(srcTrie.Hash())
|
||||
if err != nil {
|
||||
t.Fatalf("State is not available %x", srcTrie.Hash())
|
||||
}
|
||||
|
|
@ -541,7 +541,7 @@ func testIncompleteSync(t *testing.T, scheme string) {
|
|||
syncPath: NewSyncPath([]byte(paths[i])),
|
||||
})
|
||||
}
|
||||
reader, err := srcDb.Reader(srcTrie.Hash())
|
||||
reader, err := srcDb.NodeReader(srcTrie.Hash())
|
||||
if err != nil {
|
||||
t.Fatalf("State is not available %x", srcTrie.Hash())
|
||||
}
|
||||
|
|
@ -633,7 +633,7 @@ func testSyncOrdering(t *testing.T, scheme string) {
|
|||
})
|
||||
reqs = append(reqs, NewSyncPath([]byte(paths[i])))
|
||||
}
|
||||
reader, err := srcDb.Reader(srcTrie.Hash())
|
||||
reader, err := srcDb.NodeReader(srcTrie.Hash())
|
||||
if err != nil {
|
||||
t.Fatalf("State is not available %x", srcTrie.Hash())
|
||||
}
|
||||
|
|
@ -703,7 +703,7 @@ func syncWithHookWriter(t *testing.T, root common.Hash, db ethdb.Database, srcDb
|
|||
syncPath: NewSyncPath([]byte(paths[i])),
|
||||
})
|
||||
}
|
||||
reader, err := srcDb.Reader(root)
|
||||
reader, err := srcDb.NodeReader(root)
|
||||
if err != nil {
|
||||
t.Fatalf("State is not available %x", root)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ func (t *Trie) Copy() *Trie {
|
|||
// zero hash or the sha3 hash of an empty string, then trie is initially
|
||||
// empty, otherwise, the root node must be present in database or returns
|
||||
// a MissingNodeError if not.
|
||||
func New(id *ID, db database.Database) (*Trie, error) {
|
||||
func New(id *ID, db database.NodeDatabase) (*Trie, error) {
|
||||
reader, err := newTrieReader(id.StateRoot, id.Owner, db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -20,27 +20,27 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/trie/triestate"
|
||||
"github.com/ethereum/go-ethereum/triedb/database"
|
||||
"github.com/ethereum/go-ethereum/triedb/state"
|
||||
)
|
||||
|
||||
// trieReader is a wrapper of the underlying node reader. It's not safe
|
||||
// for concurrent usage.
|
||||
type trieReader struct {
|
||||
owner common.Hash
|
||||
reader database.Reader
|
||||
reader database.NodeReader
|
||||
banned map[string]struct{} // Marker to prevent node from being accessed, for tests
|
||||
}
|
||||
|
||||
// newTrieReader initializes the trie reader with the given node reader.
|
||||
func newTrieReader(stateRoot, owner common.Hash, db database.Database) (*trieReader, error) {
|
||||
func newTrieReader(stateRoot, owner common.Hash, db database.NodeDatabase) (*trieReader, error) {
|
||||
if stateRoot == (common.Hash{}) || stateRoot == types.EmptyRootHash {
|
||||
if stateRoot == (common.Hash{}) {
|
||||
log.Error("Zero state root hash!")
|
||||
}
|
||||
return &trieReader{owner: owner}, nil
|
||||
}
|
||||
reader, err := db.Reader(stateRoot)
|
||||
reader, err := db.NodeReader(stateRoot)
|
||||
if err != nil {
|
||||
return nil, &MissingNodeError{Owner: owner, NodeHash: stateRoot, err: err}
|
||||
}
|
||||
|
|
@ -73,22 +73,22 @@ func (r *trieReader) node(path []byte, hash common.Hash) ([]byte, error) {
|
|||
return blob, nil
|
||||
}
|
||||
|
||||
// MerkleLoader implements triestate.TrieLoader for constructing tries.
|
||||
type MerkleLoader struct {
|
||||
db database.Database
|
||||
// MerkleOpener implements state.TrieOpener for constructing tries.
|
||||
type MerkleOpener struct {
|
||||
db database.NodeDatabase
|
||||
}
|
||||
|
||||
// NewMerkleLoader creates the merkle trie loader.
|
||||
func NewMerkleLoader(db database.Database) *MerkleLoader {
|
||||
return &MerkleLoader{db: db}
|
||||
// NewMerkleOpener creates the merkle trie opener.
|
||||
func NewMerkleOpener(db database.NodeDatabase) state.TrieOpener {
|
||||
return &MerkleOpener{db: db}
|
||||
}
|
||||
|
||||
// OpenTrie opens the main account trie.
|
||||
func (l *MerkleLoader) OpenTrie(root common.Hash) (triestate.Trie, error) {
|
||||
func (l *MerkleOpener) OpenTrie(root common.Hash) (state.Trie, error) {
|
||||
return New(TrieID(root), l.db)
|
||||
}
|
||||
|
||||
// OpenStorageTrie opens the storage trie of an account.
|
||||
func (l *MerkleLoader) OpenStorageTrie(stateRoot common.Hash, addrHash, root common.Hash) (triestate.Trie, error) {
|
||||
func (l *MerkleOpener) OpenStorageTrie(stateRoot common.Hash, addrHash, root common.Hash) (state.Trie, error) {
|
||||
return New(StorageTrieID(stateRoot, addrHash, root), l.db)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ type VerkleTrie struct {
|
|||
}
|
||||
|
||||
// NewVerkleTrie constructs a verkle tree based on the specified root hash.
|
||||
func NewVerkleTrie(root common.Hash, db database.Database, cache *utils.PointCache) (*VerkleTrie, error) {
|
||||
func NewVerkleTrie(root common.Hash, db database.NodeDatabase, cache *utils.PointCache) (*VerkleTrie, error) {
|
||||
reader, err := newTrieReader(root, common.Hash{}, db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
61
triedb/config.go
Normal file
61
triedb/config.go
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
// Copyright 2024 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 triedb
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
)
|
||||
|
||||
// Config defines all options for configuring database.
|
||||
type Config struct {
|
||||
Preimages bool // Flag whether the preimage of node key is recorded
|
||||
IsVerkle bool // Flag whether the db is holding a verkle tree
|
||||
HashDB *hashdb.Config // Configs for hash-based scheme
|
||||
PathDB *pathdb.Config // Configs for experimental path-based scheme
|
||||
}
|
||||
|
||||
// sanitize validates the provided config.
|
||||
func (config *Config) sanitize() error {
|
||||
if config == nil {
|
||||
return errors.New("config is nil")
|
||||
}
|
||||
if config.HashDB != nil && config.PathDB != nil {
|
||||
return errors.New("both 'hash' and 'path' mode are configured")
|
||||
}
|
||||
if config.HashDB == nil && config.PathDB == nil {
|
||||
return errors.New("neither 'hash' nor 'path' mode is configured")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Copy returns a deep copied config object.
|
||||
func (config *Config) Copy() *Config {
|
||||
cpy := &Config{
|
||||
Preimages: config.Preimages,
|
||||
IsVerkle: config.IsVerkle,
|
||||
}
|
||||
if config.HashDB != nil {
|
||||
cpy.HashDB = config.HashDB.Copy()
|
||||
}
|
||||
if config.PathDB != nil {
|
||||
cpy.PathDB = config.PathDB.Copy()
|
||||
}
|
||||
return cpy
|
||||
}
|
||||
|
|
@ -22,29 +22,13 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"github.com/ethereum/go-ethereum/trie/triestate"
|
||||
"github.com/ethereum/go-ethereum/triedb/database"
|
||||
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/state"
|
||||
)
|
||||
|
||||
// Config defines all necessary options for database.
|
||||
type Config struct {
|
||||
Preimages bool // Flag whether the preimage of node key is recorded
|
||||
IsVerkle bool // Flag whether the db is holding a verkle tree
|
||||
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
|
||||
// default settings.
|
||||
var HashDefaults = &Config{
|
||||
Preimages: false,
|
||||
HashDB: hashdb.Defaults,
|
||||
}
|
||||
|
||||
// backend defines the methods needed to access/update trie nodes in different
|
||||
// state scheme.
|
||||
type backend interface {
|
||||
|
|
@ -62,13 +46,17 @@ type backend interface {
|
|||
// and dirty disk layer nodes, so both are merged into the second return.
|
||||
Size() (common.StorageSize, common.StorageSize)
|
||||
|
||||
// NodeReader returns a node reader associated with the specific state.
|
||||
// An error will be returned if the specified state is not available.
|
||||
NodeReader(root common.Hash) (database.NodeReader, error)
|
||||
|
||||
// Update performs a state transition by committing dirty nodes contained
|
||||
// in the given set in order to update state from the specified parent to
|
||||
// the specified root.
|
||||
//
|
||||
// The passed in maps(nodes, states) will be retained to avoid copying
|
||||
// everything. Therefore, these maps must not be changed afterwards.
|
||||
Update(root common.Hash, parent common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *triestate.Set) error
|
||||
Update(root common.Hash, parent common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *state.Origin) error
|
||||
|
||||
// Commit writes all relevant trie nodes belonging to the specified state
|
||||
// to disk. Report specifies whether logs will be displayed in info level.
|
||||
|
|
@ -91,9 +79,8 @@ type Database struct {
|
|||
// NewDatabase initializes the trie database with default settings, note
|
||||
// the legacy hash-based scheme is used by default.
|
||||
func NewDatabase(diskdb ethdb.Database, config *Config) *Database {
|
||||
// Sanitize the config and use the default one if it's not specified.
|
||||
if config == nil {
|
||||
config = HashDefaults
|
||||
if err := config.sanitize(); err != nil {
|
||||
log.Crit("Database config is invalid", "error", err)
|
||||
}
|
||||
var preimages *preimageStore
|
||||
if config.Preimages {
|
||||
|
|
@ -104,34 +91,18 @@ func NewDatabase(diskdb ethdb.Database, config *Config) *Database {
|
|||
diskdb: diskdb,
|
||||
preimages: preimages,
|
||||
}
|
||||
if config.HashDB != nil && config.PathDB != nil {
|
||||
log.Crit("Both 'hash' and 'path' mode are configured")
|
||||
}
|
||||
if config.PathDB != nil {
|
||||
db.backend = pathdb.New(diskdb, config.PathDB)
|
||||
} else {
|
||||
var resolver hashdb.ChildResolver
|
||||
if config.IsVerkle {
|
||||
// TODO define verkle resolver
|
||||
log.Crit("Verkle node resolver is not defined")
|
||||
} else {
|
||||
resolver = trie.MerkleResolver{}
|
||||
}
|
||||
db.backend = hashdb.New(diskdb, config.HashDB, resolver)
|
||||
db.backend = hashdb.New(diskdb, config.HashDB)
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
// Reader returns a reader for accessing all trie nodes with provided state root.
|
||||
// An error will be returned if the requested state is not available.
|
||||
func (db *Database) Reader(blockRoot common.Hash) (database.Reader, error) {
|
||||
switch b := db.backend.(type) {
|
||||
case *hashdb.Database:
|
||||
return b.Reader(blockRoot)
|
||||
case *pathdb.Database:
|
||||
return b.Reader(blockRoot)
|
||||
}
|
||||
return nil, errors.New("unknown backend")
|
||||
// NodeReader returns a reader for accessing all trie nodes with provided state
|
||||
// root. An error will be returned if the requested state is not available.
|
||||
func (db *Database) NodeReader(blockRoot common.Hash) (database.NodeReader, error) {
|
||||
return db.backend.NodeReader(blockRoot)
|
||||
}
|
||||
|
||||
// Update performs a state transition by committing dirty nodes contained in the
|
||||
|
|
@ -141,7 +112,7 @@ func (db *Database) Reader(blockRoot common.Hash) (database.Reader, error) {
|
|||
//
|
||||
// The passed in maps(nodes, states) will be retained to avoid copying everything.
|
||||
// Therefore, these maps must not be changed afterwards.
|
||||
func (db *Database) Update(root common.Hash, parent common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *triestate.Set) error {
|
||||
func (db *Database) Update(root common.Hash, parent common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *state.Origin) error {
|
||||
if db.preimages != nil {
|
||||
db.preimages.commit(false)
|
||||
}
|
||||
|
|
@ -265,14 +236,7 @@ func (db *Database) Recover(target common.Hash) error {
|
|||
if !ok {
|
||||
return errors.New("not supported")
|
||||
}
|
||||
var loader triestate.TrieLoader
|
||||
if db.config.IsVerkle {
|
||||
// TODO define verkle loader
|
||||
log.Crit("Verkle loader is not defined")
|
||||
} else {
|
||||
loader = trie.NewMerkleLoader(db)
|
||||
}
|
||||
return pdb.Recover(target, loader)
|
||||
return pdb.Recover(target)
|
||||
}
|
||||
|
||||
// Recoverable returns the indicator if the specified state is enabled to be
|
||||
|
|
|
|||
|
|
@ -16,18 +16,23 @@
|
|||
|
||||
package database
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
import "github.com/ethereum/go-ethereum/common"
|
||||
|
||||
// Reader wraps the Node method of a backing trie reader.
|
||||
type Reader interface {
|
||||
// NodeReader wraps the Node method of a backing trie reader.
|
||||
type NodeReader interface {
|
||||
// Node retrieves the trie node blob with the provided trie identifier,
|
||||
// node path and the corresponding node hash. No error will be returned
|
||||
// if the node is not found.
|
||||
Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, error)
|
||||
}
|
||||
|
||||
// NodeDatabase warps the methods of a backing trie store.
|
||||
type NodeDatabase interface {
|
||||
// NodeReader returns a node reader associated with the specific state.
|
||||
// An error will be returned if the specified state is not available.
|
||||
NodeReader(stateRoot common.Hash) (NodeReader, error)
|
||||
}
|
||||
|
||||
// PreimageStore wraps the methods of a backing store for reading and writing
|
||||
// trie node preimages.
|
||||
type PreimageStore interface {
|
||||
|
|
@ -41,8 +46,5 @@ type PreimageStore interface {
|
|||
// Database wraps the methods of a backing trie store.
|
||||
type Database interface {
|
||||
PreimageStore
|
||||
|
||||
// Reader returns a node reader associated with the specific state.
|
||||
// An error will be returned if the specified state is not available.
|
||||
Reader(stateRoot common.Hash) (Reader, error)
|
||||
NodeDatabase
|
||||
}
|
||||
|
|
|
|||
62
triedb/dbconfig/config.go
Normal file
62
triedb/dbconfig/config.go
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright 2024 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 dbconfig
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
)
|
||||
|
||||
// HashDefaults represents a configuration for using a hash-based scheme with
|
||||
// default settings. The default configuration is assumed immutable, so please
|
||||
// deep-copy the configuration if any mutation is expected.
|
||||
var HashDefaults = triedb.Config{
|
||||
Preimages: false,
|
||||
IsVerkle: false,
|
||||
HashDB: &hashdb.Config{
|
||||
// Explicitly set clean cache size to zero as default to avoid
|
||||
// creating fastcache, otherwise database must be closed when
|
||||
// it's no longer needed to prevent memory leak.
|
||||
CleanCacheSize: 0,
|
||||
|
||||
// Merkle trie resolver is used as the default node resolver.
|
||||
ChildResolver: trie.MerkleResolver,
|
||||
},
|
||||
}
|
||||
|
||||
// PathDefaults represents a configuration for using a path-based scheme with
|
||||
// default settings. The default configuration is assumed immutable, so please
|
||||
// deep-copy the configuration if any mutation is expected.
|
||||
var PathDefaults = triedb.Config{
|
||||
Preimages: false,
|
||||
IsVerkle: false,
|
||||
PathDB: &pathdb.Config{
|
||||
StateHistory: params.FullImmutabilityThreshold,
|
||||
|
||||
// Explicitly set clean cache size to zero as default to avoid
|
||||
// creating fastcache, otherwise database must be closed when
|
||||
// it's no longer needed to prevent memory leak.
|
||||
CleanCacheSize: 0,
|
||||
DirtyCacheSize: pathdb.DefaultBufferSize,
|
||||
|
||||
// Merkle trie loader is used as the default trie loader.
|
||||
TrieOpener: trie.NewMerkleOpener,
|
||||
},
|
||||
}
|
||||
|
|
@ -32,7 +32,8 @@ import (
|
|||
"github.com/ethereum/go-ethereum/metrics"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"github.com/ethereum/go-ethereum/trie/triestate"
|
||||
"github.com/ethereum/go-ethereum/triedb/database"
|
||||
"github.com/ethereum/go-ethereum/triedb/state"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -59,24 +60,34 @@ var (
|
|||
memcacheCommitBytesMeter = metrics.NewRegisteredMeter("hashdb/memcache/commit/bytes", nil)
|
||||
)
|
||||
|
||||
// ChildResolver defines the required method to decode the provided
|
||||
// trie node and iterate the children on top.
|
||||
type ChildResolver interface {
|
||||
ForEach(node []byte, onChild func(common.Hash))
|
||||
}
|
||||
|
||||
// Config contains the settings for database.
|
||||
type Config struct {
|
||||
CleanCacheSize int // Maximum memory allowance (in bytes) for caching clean nodes
|
||||
// CleanCacheSize specifies the maximum memory allowance (in bytes)
|
||||
// for caching clean nodes.
|
||||
CleanCacheSize int
|
||||
|
||||
// ChildResolver defines the method to decode the provided trie node
|
||||
// and iterate the hash children on top.
|
||||
ChildResolver func(node []byte, onChild func(common.Hash))
|
||||
}
|
||||
|
||||
// Defaults is the default setting for database if it's not specified.
|
||||
// Notably, clean cache is disabled explicitly,
|
||||
var Defaults = &Config{
|
||||
// Explicitly set clean cache size to 0 to avoid creating fastcache,
|
||||
// otherwise database must be closed when it's no longer needed to
|
||||
// prevent memory leak.
|
||||
CleanCacheSize: 0,
|
||||
// sanitize validates the provided config.
|
||||
func (config *Config) sanitize() error {
|
||||
if config == nil {
|
||||
return errors.New("hashdb config is nil")
|
||||
}
|
||||
if config.ChildResolver == nil {
|
||||
return errors.New("node resolver is not configured")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Copy returns a deep copied config object.
|
||||
func (config *Config) Copy() *Config {
|
||||
return &Config{
|
||||
CleanCacheSize: config.CleanCacheSize,
|
||||
ChildResolver: config.ChildResolver,
|
||||
}
|
||||
}
|
||||
|
||||
// Database is an intermediate write layer between the trie data structures and
|
||||
|
|
@ -84,7 +95,7 @@ var Defaults = &Config{
|
|||
// periodically flush a couple tries to disk, garbage collecting the remainder.
|
||||
type Database struct {
|
||||
diskdb ethdb.Database // Persistent storage for matured trie nodes
|
||||
resolver ChildResolver // The handler to resolve children of nodes
|
||||
config *Config // configuration used in hash db
|
||||
|
||||
cleans *fastcache.Cache // GC friendly memory cache of clean node RLPs
|
||||
dirties map[common.Hash]*cachedNode // Data and references relationships of dirty trie nodes
|
||||
|
|
@ -123,17 +134,17 @@ var cachedNodeSize = int(reflect.TypeOf(cachedNode{}).Size())
|
|||
// forChildren invokes the callback for all the tracked children of this node,
|
||||
// both the implicit ones from inside the node as well as the explicit ones
|
||||
// from outside the node.
|
||||
func (n *cachedNode) forChildren(resolver ChildResolver, onChild func(hash common.Hash)) {
|
||||
func (n *cachedNode) forChildren(resolver func(node []byte, onChild func(common.Hash)), onChild func(hash common.Hash)) {
|
||||
for child := range n.external {
|
||||
onChild(child)
|
||||
}
|
||||
resolver.ForEach(n.node, onChild)
|
||||
resolver(n.node, onChild)
|
||||
}
|
||||
|
||||
// New initializes the hash-based node database.
|
||||
func New(diskdb ethdb.Database, config *Config, resolver ChildResolver) *Database {
|
||||
if config == nil {
|
||||
config = Defaults
|
||||
func New(diskdb ethdb.Database, config *Config) *Database {
|
||||
if err := config.sanitize(); err != nil {
|
||||
log.Crit("Hash database config is invalid", "error", err)
|
||||
}
|
||||
var cleans *fastcache.Cache
|
||||
if config.CleanCacheSize > 0 {
|
||||
|
|
@ -141,7 +152,7 @@ func New(diskdb ethdb.Database, config *Config, resolver ChildResolver) *Databas
|
|||
}
|
||||
return &Database{
|
||||
diskdb: diskdb,
|
||||
resolver: resolver,
|
||||
config: config,
|
||||
cleans: cleans,
|
||||
dirties: make(map[common.Hash]*cachedNode),
|
||||
}
|
||||
|
|
@ -162,7 +173,7 @@ func (db *Database) insert(hash common.Hash, node []byte) {
|
|||
node: node,
|
||||
flushPrev: db.newest,
|
||||
}
|
||||
entry.forChildren(db.resolver, func(child common.Hash) {
|
||||
entry.forChildren(db.config.ChildResolver, func(child common.Hash) {
|
||||
if c := db.dirties[child]; c != nil {
|
||||
c.parents++
|
||||
}
|
||||
|
|
@ -315,7 +326,7 @@ func (db *Database) dereference(hash common.Hash) {
|
|||
db.dirties[node.flushNext].flushPrev = node.flushPrev
|
||||
}
|
||||
// Dereference all children and delete the node
|
||||
node.forChildren(db.resolver, func(child common.Hash) {
|
||||
node.forChildren(db.config.ChildResolver, func(child common.Hash) {
|
||||
db.dereference(child)
|
||||
})
|
||||
delete(db.dirties, hash)
|
||||
|
|
@ -464,7 +475,7 @@ func (db *Database) commit(hash common.Hash, batch ethdb.Batch, uncacher *cleane
|
|||
var err error
|
||||
|
||||
// Dereference all children and delete the node
|
||||
node.forChildren(db.resolver, func(child common.Hash) {
|
||||
node.forChildren(db.config.ChildResolver, func(child common.Hash) {
|
||||
if err == nil {
|
||||
err = db.commit(child, batch, uncacher)
|
||||
}
|
||||
|
|
@ -548,7 +559,7 @@ func (db *Database) Initialized(genesisRoot common.Hash) bool {
|
|||
|
||||
// Update inserts the dirty nodes in provided nodeset into database and link the
|
||||
// account trie with multiple storage tries if necessary.
|
||||
func (db *Database) Update(root common.Hash, parent common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *triestate.Set) error {
|
||||
func (db *Database) Update(root common.Hash, parent common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *state.Origin) error {
|
||||
// Ensure the parent state is present and signal a warning if not.
|
||||
if parent != types.EmptyRootHash {
|
||||
if blob, _ := db.node(parent); len(blob) == 0 {
|
||||
|
|
@ -629,9 +640,9 @@ func (db *Database) Scheme() string {
|
|||
return rawdb.HashScheme
|
||||
}
|
||||
|
||||
// Reader retrieves a node reader belonging to the given state root.
|
||||
// NodeReader retrieves a node reader belonging to the given state root.
|
||||
// An error will be returned if the requested state is not available.
|
||||
func (db *Database) Reader(root common.Hash) (*reader, error) {
|
||||
func (db *Database) NodeReader(root common.Hash) (database.NodeReader, error) {
|
||||
if _, err := db.node(root); err != nil {
|
||||
return nil, fmt.Errorf("state %#x is not available, %v", root, err)
|
||||
}
|
||||
|
|
|
|||
63
triedb/pathdb/config.go
Normal file
63
triedb/pathdb/config.go
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright 2024 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 pathdb
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/triedb/database"
|
||||
"github.com/ethereum/go-ethereum/triedb/state"
|
||||
)
|
||||
|
||||
// Config contains the settings for database.
|
||||
type Config struct {
|
||||
StateHistory uint64 // Number of recent blocks to maintain state history for
|
||||
CleanCacheSize int // Maximum memory allowance (in bytes) for caching clean nodes
|
||||
DirtyCacheSize int // Maximum memory allowance (in bytes) for caching dirty nodes
|
||||
ReadOnly bool // Flag whether the database is opened in read only mode.
|
||||
TrieOpener func(db database.NodeDatabase) state.TrieOpener // Function to create trie loader for trie state transition
|
||||
}
|
||||
|
||||
// sanitize checks the provided user configurations and changes anything that's
|
||||
// unreasonable or unworkable.
|
||||
func (c *Config) sanitize() (*Config, error) {
|
||||
if c == nil {
|
||||
return nil, errors.New("pathdb config is nil")
|
||||
}
|
||||
if c.TrieOpener == nil {
|
||||
return nil, errors.New("trie opener is not configured")
|
||||
}
|
||||
conf := *c
|
||||
if conf.DirtyCacheSize > maxBufferSize {
|
||||
log.Warn("Sanitizing invalid node buffer size", "provided", common.StorageSize(conf.DirtyCacheSize), "updated", common.StorageSize(maxBufferSize))
|
||||
conf.DirtyCacheSize = maxBufferSize
|
||||
}
|
||||
return &conf, nil
|
||||
}
|
||||
|
||||
// Copy returns a deep copied config object.
|
||||
func (c *Config) Copy() *Config {
|
||||
return &Config{
|
||||
StateHistory: c.StateHistory,
|
||||
CleanCacheSize: c.CleanCacheSize,
|
||||
DirtyCacheSize: c.DirtyCacheSize,
|
||||
ReadOnly: c.ReadOnly,
|
||||
TrieOpener: c.TrieOpener,
|
||||
}
|
||||
}
|
||||
|
|
@ -28,17 +28,14 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"github.com/ethereum/go-ethereum/trie/triestate"
|
||||
"github.com/ethereum/go-ethereum/triedb/database"
|
||||
"github.com/ethereum/go-ethereum/triedb/state"
|
||||
)
|
||||
|
||||
const (
|
||||
// maxDiffLayers is the maximum diff layers allowed in the layer tree.
|
||||
maxDiffLayers = 128
|
||||
|
||||
// defaultCleanSize is the default memory allowance of clean cache.
|
||||
defaultCleanSize = 16 * 1024 * 1024
|
||||
// DefaultCleanSize is the default memory allowance of clean cache.
|
||||
DefaultCleanSize = 16 * 1024 * 1024
|
||||
|
||||
// maxBufferSize is the maximum memory allowance of node buffer.
|
||||
// Too large nodebuffer will cause the system to pause for a long
|
||||
|
|
@ -54,6 +51,9 @@ const (
|
|||
DefaultBufferSize = 64 * 1024 * 1024
|
||||
)
|
||||
|
||||
// maxDiffLayers is the maximum diff layers allowed in the layer tree.
|
||||
var maxDiffLayers = 128
|
||||
|
||||
// layer is the interface implemented by all state layers which includes some
|
||||
// public methods and some additional methods for internal usage.
|
||||
type layer interface {
|
||||
|
|
@ -76,7 +76,7 @@ type layer interface {
|
|||
// the provided dirty trie nodes along with the state change set.
|
||||
//
|
||||
// Note, the maps are retained by the method to avoid copying everything.
|
||||
update(root common.Hash, id uint64, block uint64, nodes map[common.Hash]map[string]*trienode.Node, states *triestate.Set) *diffLayer
|
||||
update(root common.Hash, id uint64, block uint64, nodes map[common.Hash]map[string]*trienode.Node, states *state.Origin) *diffLayer
|
||||
|
||||
// journal commits an entire diff hierarchy to disk into a single journal entry.
|
||||
// This is meant to be used during shutdown to persist the layer without
|
||||
|
|
@ -84,35 +84,6 @@ type layer interface {
|
|||
journal(w io.Writer) error
|
||||
}
|
||||
|
||||
// Config contains the settings for database.
|
||||
type Config struct {
|
||||
StateHistory uint64 // Number of recent blocks to maintain state history for
|
||||
CleanCacheSize int // Maximum memory allowance (in bytes) for caching clean nodes
|
||||
DirtyCacheSize int // Maximum memory allowance (in bytes) for caching dirty nodes
|
||||
ReadOnly bool // Flag whether the database is opened in read only mode.
|
||||
}
|
||||
|
||||
// sanitize checks the provided user configurations and changes anything that's
|
||||
// unreasonable or unworkable.
|
||||
func (c *Config) sanitize() *Config {
|
||||
conf := *c
|
||||
if conf.DirtyCacheSize > maxBufferSize {
|
||||
log.Warn("Sanitizing invalid node buffer size", "provided", common.StorageSize(conf.DirtyCacheSize), "updated", common.StorageSize(maxBufferSize))
|
||||
conf.DirtyCacheSize = maxBufferSize
|
||||
}
|
||||
return &conf
|
||||
}
|
||||
|
||||
// Defaults contains default settings for Ethereum mainnet.
|
||||
var Defaults = &Config{
|
||||
StateHistory: params.FullImmutabilityThreshold,
|
||||
CleanCacheSize: defaultCleanSize,
|
||||
DirtyCacheSize: DefaultBufferSize,
|
||||
}
|
||||
|
||||
// ReadOnly is the config in order to open database in read only mode.
|
||||
var ReadOnly = &Config{ReadOnly: true}
|
||||
|
||||
// Database is a multiple-layered structure for maintaining in-memory trie nodes.
|
||||
// It consists of one persistent base layer backed by a key-value store, on top
|
||||
// of which arbitrarily many in-memory diff layers are stacked. The memory diffs
|
||||
|
|
@ -135,6 +106,7 @@ type Database struct {
|
|||
diskdb ethdb.Database // Persistent storage for matured trie nodes
|
||||
tree *layerTree // The group for all known layers
|
||||
freezer *rawdb.ResettableFreezer // Freezer for storing trie histories, nil possible in tests
|
||||
trieOpener state.TrieOpener // Trie loader to open trie for state recovering
|
||||
lock sync.RWMutex // Lock to prevent mutations from happening at the same time
|
||||
}
|
||||
|
||||
|
|
@ -142,11 +114,10 @@ type Database struct {
|
|||
// store (with a number of memory layers from a journal). If the journal is not
|
||||
// matched with the base persistent layer, all the recorded diff layers are discarded.
|
||||
func New(diskdb ethdb.Database, config *Config) *Database {
|
||||
if config == nil {
|
||||
config = Defaults
|
||||
config, err := config.sanitize()
|
||||
if err != nil {
|
||||
log.Crit("Path database config is invalid", "err", err)
|
||||
}
|
||||
config = config.sanitize()
|
||||
|
||||
db := &Database{
|
||||
readOnly: config.ReadOnly,
|
||||
bufferSize: config.DirtyCacheSize,
|
||||
|
|
@ -156,6 +127,7 @@ func New(diskdb ethdb.Database, config *Config) *Database {
|
|||
// Construct the layer tree by resolving the in-disk singleton state
|
||||
// and in-memory layer journal.
|
||||
db.tree = newLayerTree(db.loadLayers())
|
||||
db.trieOpener = db.config.TrieOpener(db)
|
||||
|
||||
// Open the freezer for state history if the passed database contains an
|
||||
// ancient store. Otherwise, all the relevant functionalities are disabled.
|
||||
|
|
@ -206,8 +178,8 @@ func New(diskdb ethdb.Database, config *Config) *Database {
|
|||
return db
|
||||
}
|
||||
|
||||
// Reader retrieves a layer belonging to the given state root.
|
||||
func (db *Database) Reader(root common.Hash) (layer, error) {
|
||||
// NodeReader retrieves a layer belonging to the given state root.
|
||||
func (db *Database) NodeReader(root common.Hash) (database.NodeReader, error) {
|
||||
l := db.tree.get(root)
|
||||
if l == nil {
|
||||
return nil, fmt.Errorf("state %#x is not available", root)
|
||||
|
|
@ -222,7 +194,7 @@ func (db *Database) Reader(root common.Hash) (layer, error) {
|
|||
//
|
||||
// The passed in maps(nodes, states) will be retained to avoid copying everything.
|
||||
// Therefore, these maps must not be changed afterwards.
|
||||
func (db *Database) Update(root common.Hash, parentRoot common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *triestate.Set) error {
|
||||
func (db *Database) Update(root common.Hash, parentRoot common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *state.Origin) error {
|
||||
// Hold the lock to prevent concurrent mutations.
|
||||
db.lock.Lock()
|
||||
defer db.lock.Unlock()
|
||||
|
|
@ -331,7 +303,7 @@ func (db *Database) Enable(root common.Hash) error {
|
|||
// Recover rollbacks the database to a specified historical point.
|
||||
// The state is supported as the rollback destination only if it's
|
||||
// canonical state and the corresponding trie histories are existent.
|
||||
func (db *Database) Recover(root common.Hash, loader triestate.TrieLoader) error {
|
||||
func (db *Database) Recover(root common.Hash) error {
|
||||
db.lock.Lock()
|
||||
defer db.lock.Unlock()
|
||||
|
||||
|
|
@ -357,7 +329,7 @@ func (db *Database) Recover(root common.Hash, loader triestate.TrieLoader) error
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dl, err = dl.revert(h, loader)
|
||||
dl, err = dl.revert(h)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,10 +27,11 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/internal/testrand"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie/testutil"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"github.com/ethereum/go-ethereum/trie/triestate"
|
||||
"github.com/ethereum/go-ethereum/triedb/database"
|
||||
"github.com/ethereum/go-ethereum/triedb/state"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
|
|
@ -54,7 +55,7 @@ func generateAccount(storageRoot common.Hash) types.StateAccount {
|
|||
return types.StateAccount{
|
||||
Nonce: uint64(rand.Intn(100)),
|
||||
Balance: uint256.NewInt(rand.Uint64()),
|
||||
CodeHash: testutil.RandBytes(32),
|
||||
CodeHash: testrand.Bytes(32),
|
||||
Root: storageRoot,
|
||||
}
|
||||
}
|
||||
|
|
@ -98,22 +99,27 @@ type tester struct {
|
|||
|
||||
func newTester(t *testing.T, historyLimit uint64) *tester {
|
||||
var (
|
||||
snapAccounts = make(map[common.Hash]map[common.Hash][]byte)
|
||||
snapStorages = make(map[common.Hash]map[common.Hash]map[common.Hash][]byte)
|
||||
disk, _ = rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false)
|
||||
db = New(disk, &Config{
|
||||
StateHistory: historyLimit,
|
||||
CleanCacheSize: 256 * 1024,
|
||||
DirtyCacheSize: 256 * 1024,
|
||||
CleanCacheSize: 16 * 1024,
|
||||
DirtyCacheSize: 16 * 1024,
|
||||
TrieOpener: func(db database.NodeDatabase) state.TrieOpener {
|
||||
return newHashOpener(snapAccounts, snapStorages)
|
||||
},
|
||||
})
|
||||
obj = &tester{
|
||||
db: db,
|
||||
preimages: make(map[common.Hash]common.Address),
|
||||
accounts: make(map[common.Hash][]byte),
|
||||
storages: make(map[common.Hash]map[common.Hash][]byte),
|
||||
snapAccounts: make(map[common.Hash]map[common.Hash][]byte),
|
||||
snapStorages: make(map[common.Hash]map[common.Hash]map[common.Hash][]byte),
|
||||
snapAccounts: snapAccounts,
|
||||
snapStorages: snapStorages,
|
||||
}
|
||||
)
|
||||
for i := 0; i < 2*128; i++ {
|
||||
for i := 0; i < 16; i++ {
|
||||
var parent = types.EmptyRootHash
|
||||
if len(obj.roots) != 0 {
|
||||
parent = obj.roots[len(obj.roots)-1]
|
||||
|
|
@ -146,8 +152,8 @@ func (t *tester) generateStorage(ctx *genctx, addr common.Address) common.Hash {
|
|||
origin = make(map[common.Hash][]byte)
|
||||
)
|
||||
for i := 0; i < 10; i++ {
|
||||
v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testutil.RandBytes(32)))
|
||||
hash := testutil.RandomHash()
|
||||
v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testrand.Bytes(32)))
|
||||
hash := testrand.Hash()
|
||||
|
||||
storage[hash] = v
|
||||
origin[hash] = nil
|
||||
|
|
@ -175,8 +181,8 @@ func (t *tester) mutateStorage(ctx *genctx, addr common.Address, root common.Has
|
|||
}
|
||||
}
|
||||
for i := 0; i < 3; i++ {
|
||||
v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testutil.RandBytes(32)))
|
||||
hash := testutil.RandomHash()
|
||||
v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testrand.Bytes(32)))
|
||||
hash := testrand.Hash()
|
||||
|
||||
storage[hash] = v
|
||||
origin[hash] = nil
|
||||
|
|
@ -209,7 +215,7 @@ func (t *tester) clearStorage(ctx *genctx, addr common.Address, root common.Hash
|
|||
return root
|
||||
}
|
||||
|
||||
func (t *tester) generate(parent common.Hash) (common.Hash, *trienode.MergedNodeSet, *triestate.Set) {
|
||||
func (t *tester) generate(parent common.Hash) (common.Hash, *trienode.MergedNodeSet, *state.Origin) {
|
||||
var (
|
||||
ctx = newCtx()
|
||||
dirties = make(map[common.Hash]struct{})
|
||||
|
|
@ -218,7 +224,7 @@ func (t *tester) generate(parent common.Hash) (common.Hash, *trienode.MergedNode
|
|||
switch rand.Intn(opLen) {
|
||||
case createAccountOp:
|
||||
// account creation
|
||||
addr := testutil.RandomAddress()
|
||||
addr := testrand.Address()
|
||||
addrHash := crypto.Keccak256Hash(addr.Bytes())
|
||||
if _, ok := t.accounts[addrHash]; ok {
|
||||
continue
|
||||
|
|
@ -299,7 +305,7 @@ func (t *tester) generate(parent common.Hash) (common.Hash, *trienode.MergedNode
|
|||
}
|
||||
}
|
||||
}
|
||||
return root, ctx.nodes, triestate.New(ctx.accountOrigin, ctx.storageOrigin)
|
||||
return root, ctx.nodes, state.NewOrigin(ctx.accountOrigin, ctx.storageOrigin)
|
||||
}
|
||||
|
||||
// lastRoot returns the latest root hash, or empty if nothing is cached.
|
||||
|
|
@ -311,7 +317,7 @@ func (t *tester) lastHash() common.Hash {
|
|||
}
|
||||
|
||||
func (t *tester) verifyState(root common.Hash) error {
|
||||
reader, err := t.db.Reader(root)
|
||||
reader, err := t.db.NodeReader(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -379,6 +385,10 @@ func (t *tester) bottomIndex() int {
|
|||
}
|
||||
|
||||
func TestDatabaseRollback(t *testing.T) {
|
||||
maxDiffLayers = 4
|
||||
defer func() {
|
||||
maxDiffLayers = 128
|
||||
}()
|
||||
// Verify state histories
|
||||
tester := newTester(t, 0)
|
||||
defer tester.release()
|
||||
|
|
@ -388,13 +398,11 @@ func TestDatabaseRollback(t *testing.T) {
|
|||
}
|
||||
// Revert database from top to bottom
|
||||
for i := tester.bottomIndex(); i >= 0; i-- {
|
||||
root := tester.roots[i]
|
||||
parent := types.EmptyRootHash
|
||||
if i > 0 {
|
||||
parent = tester.roots[i-1]
|
||||
}
|
||||
loader := newHashLoader(tester.snapAccounts[root], tester.snapStorages[root])
|
||||
if err := tester.db.Recover(parent, loader); err != nil {
|
||||
if err := tester.db.Recover(parent); err != nil {
|
||||
t.Fatalf("Failed to revert db, err: %v", err)
|
||||
}
|
||||
if i > 0 {
|
||||
|
|
@ -409,6 +417,10 @@ func TestDatabaseRollback(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDatabaseRecoverable(t *testing.T) {
|
||||
maxDiffLayers = 4
|
||||
defer func() {
|
||||
maxDiffLayers = 128
|
||||
}()
|
||||
var (
|
||||
tester = newTester(t, 0)
|
||||
index = tester.bottomIndex()
|
||||
|
|
@ -448,6 +460,10 @@ func TestDatabaseRecoverable(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDisable(t *testing.T) {
|
||||
maxDiffLayers = 4
|
||||
defer func() {
|
||||
maxDiffLayers = 128
|
||||
}()
|
||||
tester := newTester(t, 0)
|
||||
defer tester.release()
|
||||
|
||||
|
|
@ -459,7 +475,7 @@ func TestDisable(t *testing.T) {
|
|||
t.Fatalf("Invalid activation should be rejected")
|
||||
}
|
||||
if err := tester.db.Enable(stored); err != nil {
|
||||
t.Fatal("Failed to activate database")
|
||||
t.Fatalf("Failed to activate database, %v", err)
|
||||
}
|
||||
|
||||
// Ensure journal is deleted from disk
|
||||
|
|
@ -484,6 +500,10 @@ func TestDisable(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCommit(t *testing.T) {
|
||||
maxDiffLayers = 4
|
||||
defer func() {
|
||||
maxDiffLayers = 128
|
||||
}()
|
||||
tester := newTester(t, 0)
|
||||
defer tester.release()
|
||||
|
||||
|
|
@ -508,6 +528,10 @@ func TestCommit(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestJournal(t *testing.T) {
|
||||
maxDiffLayers = 4
|
||||
defer func() {
|
||||
maxDiffLayers = 128
|
||||
}()
|
||||
tester := newTester(t, 0)
|
||||
defer tester.release()
|
||||
|
||||
|
|
@ -515,7 +539,7 @@ func TestJournal(t *testing.T) {
|
|||
t.Errorf("Failed to journal, err: %v", err)
|
||||
}
|
||||
tester.db.Close()
|
||||
tester.db = New(tester.db.diskdb, nil)
|
||||
tester.db = New(tester.db.diskdb, tester.db.config)
|
||||
|
||||
// Verify states including disk layer and all diff on top.
|
||||
for i := 0; i < len(tester.roots); i++ {
|
||||
|
|
@ -532,6 +556,10 @@ func TestJournal(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCorruptedJournal(t *testing.T) {
|
||||
maxDiffLayers = 4
|
||||
defer func() {
|
||||
maxDiffLayers = 128
|
||||
}()
|
||||
tester := newTester(t, 0)
|
||||
defer tester.release()
|
||||
|
||||
|
|
@ -547,7 +575,7 @@ func TestCorruptedJournal(t *testing.T) {
|
|||
rawdb.WriteTrieJournal(tester.db.diskdb, blob)
|
||||
|
||||
// Verify states, all not-yet-written states should be discarded
|
||||
tester.db = New(tester.db.diskdb, nil)
|
||||
tester.db = New(tester.db.diskdb, tester.db.config)
|
||||
for i := 0; i < len(tester.roots); i++ {
|
||||
if tester.roots[i] == root {
|
||||
if err := tester.verifyState(root); err != nil {
|
||||
|
|
@ -574,11 +602,15 @@ func TestCorruptedJournal(t *testing.T) {
|
|||
// truncating the tail histories. This ensures that the ID of the persistent state
|
||||
// always falls within the range of [oldest-history-id, latest-history-id].
|
||||
func TestTailTruncateHistory(t *testing.T) {
|
||||
maxDiffLayers = 4
|
||||
defer func() {
|
||||
maxDiffLayers = 128
|
||||
}()
|
||||
tester := newTester(t, 10)
|
||||
defer tester.release()
|
||||
|
||||
tester.db.Close()
|
||||
tester.db = New(tester.db.diskdb, &Config{StateHistory: 10})
|
||||
tester.db = New(tester.db.diskdb, &Config{StateHistory: 10, TrieOpener: func(db database.NodeDatabase) state.TrieOpener { return nil }})
|
||||
|
||||
head, err := tester.db.freezer.Ancients()
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"github.com/ethereum/go-ethereum/trie/triestate"
|
||||
"github.com/ethereum/go-ethereum/triedb/state"
|
||||
)
|
||||
|
||||
// diffLayer represents a collection of modifications made to the in-memory tries
|
||||
|
|
@ -37,7 +37,7 @@ type diffLayer struct {
|
|||
id uint64 // Corresponding state id
|
||||
block uint64 // Associated block number
|
||||
nodes map[common.Hash]map[string]*trienode.Node // Cached trie nodes indexed by owner and path
|
||||
states *triestate.Set // Associated state change set for building history
|
||||
states *state.Origin // Associated state change set for building history
|
||||
memory uint64 // Approximate guess as to how much memory we use
|
||||
|
||||
parent layer // Parent layer modified by this one, never nil, **can be changed**
|
||||
|
|
@ -45,7 +45,7 @@ type diffLayer struct {
|
|||
}
|
||||
|
||||
// newDiffLayer creates a new diff layer on top of an existing layer.
|
||||
func newDiffLayer(parent layer, root common.Hash, id uint64, block uint64, nodes map[common.Hash]map[string]*trienode.Node, states *triestate.Set) *diffLayer {
|
||||
func newDiffLayer(parent layer, root common.Hash, id uint64, block uint64, nodes map[common.Hash]map[string]*trienode.Node, states *state.Origin) *diffLayer {
|
||||
var (
|
||||
size int64
|
||||
count int
|
||||
|
|
@ -138,7 +138,7 @@ func (dl *diffLayer) Node(owner common.Hash, path []byte, hash common.Hash) ([]b
|
|||
|
||||
// update implements the layer interface, creating a new layer on top of the
|
||||
// existing layer tree with the specified data items.
|
||||
func (dl *diffLayer) update(root common.Hash, id uint64, block uint64, nodes map[common.Hash]map[string]*trienode.Node, states *triestate.Set) *diffLayer {
|
||||
func (dl *diffLayer) update(root common.Hash, id uint64, block uint64, nodes map[common.Hash]map[string]*trienode.Node, states *state.Origin) *diffLayer {
|
||||
return newDiffLayer(dl, root, id, block, nodes, states)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ import (
|
|||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/trie/testutil"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/internal/testrand"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
)
|
||||
|
||||
|
|
@ -66,8 +67,9 @@ func benchmarkSearch(b *testing.B, depth int, total int) {
|
|||
nodes[common.Hash{}] = make(map[string]*trienode.Node)
|
||||
for i := 0; i < 3000; i++ {
|
||||
var (
|
||||
path = testutil.RandBytes(32)
|
||||
node = testutil.RandomNode()
|
||||
path = testrand.Bytes(32)
|
||||
blob = testrand.Bytes(100)
|
||||
node = trienode.New(crypto.Keccak256Hash(blob), blob)
|
||||
)
|
||||
nodes[common.Hash{}][string(path)] = trienode.New(node.Hash, node.Blob)
|
||||
if npath == nil && depth == index {
|
||||
|
|
@ -112,8 +114,9 @@ func BenchmarkPersist(b *testing.B) {
|
|||
nodes[common.Hash{}] = make(map[string]*trienode.Node)
|
||||
for i := 0; i < 3000; i++ {
|
||||
var (
|
||||
path = testutil.RandBytes(32)
|
||||
node = testutil.RandomNode()
|
||||
path = testrand.Bytes(32)
|
||||
blob = testrand.Bytes(100)
|
||||
node = trienode.New(crypto.Keccak256Hash(blob), blob)
|
||||
)
|
||||
nodes[common.Hash{}][string(path)] = trienode.New(node.Hash, node.Blob)
|
||||
}
|
||||
|
|
@ -149,8 +152,9 @@ func BenchmarkJournal(b *testing.B) {
|
|||
nodes[common.Hash{}] = make(map[string]*trienode.Node)
|
||||
for i := 0; i < 3000; i++ {
|
||||
var (
|
||||
path = testutil.RandBytes(32)
|
||||
node = testutil.RandomNode()
|
||||
path = testrand.Bytes(32)
|
||||
blob = testrand.Bytes(100)
|
||||
node = trienode.New(crypto.Keccak256Hash(blob), blob)
|
||||
)
|
||||
nodes[common.Hash{}][string(path)] = trienode.New(node.Hash, node.Blob)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"github.com/ethereum/go-ethereum/trie/triestate"
|
||||
"github.com/ethereum/go-ethereum/triedb/state"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
|
|
@ -160,7 +160,7 @@ func (dl *diskLayer) Node(owner common.Hash, path []byte, hash common.Hash) ([]b
|
|||
|
||||
// update implements the layer interface, returning a new diff layer on top
|
||||
// with the given state set.
|
||||
func (dl *diskLayer) update(root common.Hash, id uint64, block uint64, nodes map[common.Hash]map[string]*trienode.Node, states *triestate.Set) *diffLayer {
|
||||
func (dl *diskLayer) update(root common.Hash, id uint64, block uint64, nodes map[common.Hash]map[string]*trienode.Node, states *state.Origin) *diffLayer {
|
||||
return newDiffLayer(dl, root, id, block, nodes, states)
|
||||
}
|
||||
|
||||
|
|
@ -234,17 +234,28 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) {
|
|||
}
|
||||
|
||||
// revert applies the given state history and return a reverted disk layer.
|
||||
func (dl *diskLayer) revert(h *history, loader triestate.TrieLoader) (*diskLayer, error) {
|
||||
func (dl *diskLayer) revert(h *history) (*diskLayer, error) {
|
||||
if h.meta.root != dl.rootHash() {
|
||||
return nil, errUnexpectedHistory
|
||||
}
|
||||
if dl.id == 0 {
|
||||
return nil, fmt.Errorf("%w: zero state id", errStateUnrecoverable)
|
||||
}
|
||||
var (
|
||||
hasher = crypto.NewKeccakState()
|
||||
accounts = make(map[common.Hash][]byte)
|
||||
storages = make(map[common.Hash]map[common.Hash][]byte)
|
||||
)
|
||||
for addr, blob := range h.accounts {
|
||||
accounts[crypto.HashData(hasher, addr.Bytes())] = blob
|
||||
}
|
||||
for addr, storage := range h.storages {
|
||||
storages[crypto.HashData(hasher, addr.Bytes())] = storage
|
||||
}
|
||||
// Apply the reverse state changes upon the current state. This must
|
||||
// be done before holding the lock in order to access state in "this"
|
||||
// layer.
|
||||
nodes, err := triestate.Apply(h.meta.parent, h.meta.root, h.accounts, h.storages, loader)
|
||||
nodes, err := state.Apply(h.meta.parent, h.meta.root, accounts, storages, dl.db.trieOpener)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/trie/triestate"
|
||||
"github.com/ethereum/go-ethereum/triedb/state"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
|
|
@ -242,7 +242,7 @@ type history struct {
|
|||
}
|
||||
|
||||
// newHistory constructs the state history object with provided state change set.
|
||||
func newHistory(root common.Hash, parent common.Hash, block uint64, states *triestate.Set) *history {
|
||||
func newHistory(root common.Hash, parent common.Hash, block uint64, states *state.Origin) *history {
|
||||
var (
|
||||
accountList []common.Address
|
||||
storageList = make(map[common.Address][]common.Hash)
|
||||
|
|
|
|||
|
|
@ -26,32 +26,32 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/internal/testrand"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie/testutil"
|
||||
"github.com/ethereum/go-ethereum/trie/triestate"
|
||||
"github.com/ethereum/go-ethereum/triedb/state"
|
||||
)
|
||||
|
||||
// randomStateSet generates a random state change set.
|
||||
func randomStateSet(n int) *triestate.Set {
|
||||
func randomStateSet(n int) *state.Origin {
|
||||
var (
|
||||
accounts = make(map[common.Address][]byte)
|
||||
storages = make(map[common.Address]map[common.Hash][]byte)
|
||||
)
|
||||
for i := 0; i < n; i++ {
|
||||
addr := testutil.RandomAddress()
|
||||
addr := testrand.Address()
|
||||
storages[addr] = make(map[common.Hash][]byte)
|
||||
for j := 0; j < 3; j++ {
|
||||
v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testutil.RandBytes(32)))
|
||||
storages[addr][testutil.RandomHash()] = v
|
||||
v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testrand.Bytes(32)))
|
||||
storages[addr][testrand.Hash()] = v
|
||||
}
|
||||
account := generateAccount(types.EmptyRootHash)
|
||||
accounts[addr] = types.SlimAccountRLP(account)
|
||||
}
|
||||
return triestate.New(accounts, storages)
|
||||
return state.NewOrigin(accounts, storages)
|
||||
}
|
||||
|
||||
func makeHistory() *history {
|
||||
return newHistory(testutil.RandomHash(), types.EmptyRootHash, 0, randomStateSet(3))
|
||||
return newHistory(testrand.Hash(), types.EmptyRootHash, 0, randomStateSet(3))
|
||||
}
|
||||
|
||||
func makeHistories(n int) []*history {
|
||||
|
|
@ -60,7 +60,7 @@ func makeHistories(n int) []*history {
|
|||
result []*history
|
||||
)
|
||||
for i := 0; i < n; i++ {
|
||||
root := testutil.RandomHash()
|
||||
root := testrand.Hash()
|
||||
h := newHistory(root, parent, uint64(i), randomStateSet(3))
|
||||
parent = root
|
||||
result = append(result, h)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"github.com/ethereum/go-ethereum/trie/triestate"
|
||||
"github.com/ethereum/go-ethereum/triedb/state"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -239,7 +239,7 @@ func (db *Database) loadDiffLayer(parent layer, r *rlp.Stream) (layer, error) {
|
|||
}
|
||||
storages[entry.Account] = set
|
||||
}
|
||||
return db.loadDiffLayer(newDiffLayer(parent, root, parent.stateID()+1, block, nodes, triestate.New(accounts, storages)), r)
|
||||
return db.loadDiffLayer(newDiffLayer(parent, root, parent.stateID()+1, block, nodes, state.NewOrigin(accounts, storages)), r)
|
||||
}
|
||||
|
||||
// journal implements the layer interface, marshaling the un-flushed trie nodes
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"github.com/ethereum/go-ethereum/trie/triestate"
|
||||
"github.com/ethereum/go-ethereum/triedb/state"
|
||||
)
|
||||
|
||||
// layerTree is a group of state layers identified by the state root.
|
||||
|
|
@ -86,7 +86,7 @@ func (tree *layerTree) len() int {
|
|||
}
|
||||
|
||||
// add inserts a new layer into the tree if it can be linked to an existing old parent.
|
||||
func (tree *layerTree) add(root common.Hash, parentRoot common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *triestate.Set) error {
|
||||
func (tree *layerTree) add(root common.Hash, parentRoot common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *state.Origin) error {
|
||||
// Reject noop updates to avoid self-loops. This is a special case that can
|
||||
// happen for clique networks and proof-of-stake networks where empty blocks
|
||||
// don't modify the state (0 block subsidy).
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"github.com/ethereum/go-ethereum/trie/triestate"
|
||||
"github.com/ethereum/go-ethereum/triedb/state"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
|
|
@ -133,24 +133,24 @@ func hash(states map[common.Hash][]byte) (common.Hash, []byte) {
|
|||
return crypto.Keccak256Hash(input), input
|
||||
}
|
||||
|
||||
type hashLoader struct {
|
||||
accounts map[common.Hash][]byte
|
||||
storages map[common.Hash]map[common.Hash][]byte
|
||||
type hashOpener struct {
|
||||
accounts map[common.Hash]map[common.Hash][]byte
|
||||
storages map[common.Hash]map[common.Hash]map[common.Hash][]byte
|
||||
}
|
||||
|
||||
func newHashLoader(accounts map[common.Hash][]byte, storages map[common.Hash]map[common.Hash][]byte) *hashLoader {
|
||||
return &hashLoader{
|
||||
func newHashOpener(accounts map[common.Hash]map[common.Hash][]byte, storages map[common.Hash]map[common.Hash]map[common.Hash][]byte) *hashOpener {
|
||||
return &hashOpener{
|
||||
accounts: accounts,
|
||||
storages: storages,
|
||||
}
|
||||
}
|
||||
|
||||
// OpenTrie opens the main account trie.
|
||||
func (l *hashLoader) OpenTrie(root common.Hash) (triestate.Trie, error) {
|
||||
return newTestHasher(common.Hash{}, root, l.accounts)
|
||||
func (l *hashOpener) OpenTrie(root common.Hash) (state.Trie, error) {
|
||||
return newTestHasher(common.Hash{}, root, l.accounts[root])
|
||||
}
|
||||
|
||||
// OpenStorageTrie opens the storage trie of an account.
|
||||
func (l *hashLoader) OpenStorageTrie(stateRoot common.Hash, addrHash, root common.Hash) (triestate.Trie, error) {
|
||||
return newTestHasher(addrHash, root, l.storages[addrHash])
|
||||
func (l *hashOpener) OpenStorageTrie(stateRoot common.Hash, addrHash, root common.Hash) (state.Trie, error) {
|
||||
return newTestHasher(addrHash, root, l.storages[stateRoot][addrHash])
|
||||
}
|
||||
|
|
@ -14,19 +14,16 @@
|
|||
// 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 triestate
|
||||
package state
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
// Trie is an Ethereum state trie, can be implemented by Ethereum Merkle Patricia
|
||||
|
|
@ -46,8 +43,8 @@ type Trie interface {
|
|||
Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error)
|
||||
}
|
||||
|
||||
// TrieLoader wraps functions to load tries.
|
||||
type TrieLoader interface {
|
||||
// TrieOpener wraps functions to load tries.
|
||||
type TrieOpener interface {
|
||||
// OpenTrie opens the main account trie.
|
||||
OpenTrie(root common.Hash) (Trie, error)
|
||||
|
||||
|
|
@ -55,55 +52,20 @@ type TrieLoader interface {
|
|||
OpenStorageTrie(stateRoot common.Hash, addrHash, root common.Hash) (Trie, error)
|
||||
}
|
||||
|
||||
// Set represents a collection of mutated states during a state transition.
|
||||
// The value refers to the original content of state before the transition
|
||||
// is made. Nil means that the state was not present previously.
|
||||
type Set struct {
|
||||
Accounts map[common.Address][]byte // Mutated account set, nil means the account was not present
|
||||
Storages map[common.Address]map[common.Hash][]byte // Mutated storage set, nil means the slot was not present
|
||||
size common.StorageSize // Approximate size of set
|
||||
}
|
||||
|
||||
// New constructs the state set with provided data.
|
||||
func New(accounts map[common.Address][]byte, storages map[common.Address]map[common.Hash][]byte) *Set {
|
||||
return &Set{
|
||||
Accounts: accounts,
|
||||
Storages: storages,
|
||||
}
|
||||
}
|
||||
|
||||
// Size returns the approximate memory size occupied by the set.
|
||||
func (s *Set) Size() common.StorageSize {
|
||||
if s.size != 0 {
|
||||
return s.size
|
||||
}
|
||||
for _, account := range s.Accounts {
|
||||
s.size += common.StorageSize(common.AddressLength + len(account))
|
||||
}
|
||||
for _, slots := range s.Storages {
|
||||
for _, val := range slots {
|
||||
s.size += common.StorageSize(common.HashLength + len(val))
|
||||
}
|
||||
s.size += common.StorageSize(common.AddressLength)
|
||||
}
|
||||
return s.size
|
||||
}
|
||||
|
||||
// context wraps all fields for executing state diffs.
|
||||
type context struct {
|
||||
prevRoot common.Hash
|
||||
postRoot common.Hash
|
||||
accounts map[common.Address][]byte
|
||||
storages map[common.Address]map[common.Hash][]byte
|
||||
accounts map[common.Hash][]byte
|
||||
storages map[common.Hash]map[common.Hash][]byte
|
||||
accountTrie Trie
|
||||
nodes *trienode.MergedNodeSet
|
||||
}
|
||||
|
||||
// Apply traverses the provided state diffs, apply them in the associated
|
||||
// post-state and return the generated dirty trie nodes. The state can be
|
||||
// loaded via the provided trie loader.
|
||||
func Apply(prevRoot common.Hash, postRoot common.Hash, accounts map[common.Address][]byte, storages map[common.Address]map[common.Hash][]byte, loader TrieLoader) (map[common.Hash]map[string]*trienode.Node, error) {
|
||||
tr, err := loader.OpenTrie(postRoot)
|
||||
// Apply traverses the provided state diffs, applying them in the associated
|
||||
// post-state and return the produced trie changes.
|
||||
func Apply(prevRoot common.Hash, postRoot common.Hash, accounts map[common.Hash][]byte, storages map[common.Hash]map[common.Hash][]byte, opener TrieOpener) (map[common.Hash]map[string]*trienode.Node, error) {
|
||||
tr, err := opener.OpenTrie(postRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -115,12 +77,12 @@ func Apply(prevRoot common.Hash, postRoot common.Hash, accounts map[common.Addre
|
|||
accountTrie: tr,
|
||||
nodes: trienode.NewMergedNodeSet(),
|
||||
}
|
||||
for addr, account := range accounts {
|
||||
for addrHash, account := range accounts {
|
||||
var err error
|
||||
if len(account) == 0 {
|
||||
err = deleteAccount(ctx, loader, addr)
|
||||
err = deleteAccount(ctx, opener, addrHash)
|
||||
} else {
|
||||
err = updateAccount(ctx, loader, addr)
|
||||
err = updateAccount(ctx, opener, addrHash)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to revert state, err: %w", err)
|
||||
|
|
@ -142,14 +104,10 @@ func Apply(prevRoot common.Hash, postRoot common.Hash, accounts map[common.Addre
|
|||
// updateAccount the account was present in prev-state, and may or may not
|
||||
// existent in post-state. Apply the reverse diff and verify if the storage
|
||||
// root matches the one in prev-state account.
|
||||
func updateAccount(ctx *context, loader TrieLoader, addr common.Address) error {
|
||||
func updateAccount(ctx *context, opener TrieOpener, addrHash common.Hash) error {
|
||||
// The account was present in prev-state, decode it from the
|
||||
// 'slim-rlp' format bytes.
|
||||
h := newHasher()
|
||||
defer h.release()
|
||||
|
||||
addrHash := h.hash(addr.Bytes())
|
||||
prev, err := types.FullAccount(ctx.accounts[addr])
|
||||
prev, err := types.FullAccount(ctx.accounts[addrHash])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -166,11 +124,11 @@ func updateAccount(ctx *context, loader TrieLoader, addr common.Address) error {
|
|||
}
|
||||
}
|
||||
// Apply all storage changes into the post-state storage trie.
|
||||
st, err := loader.OpenStorageTrie(ctx.postRoot, addrHash, post.Root)
|
||||
st, err := opener.OpenStorageTrie(ctx.postRoot, addrHash, post.Root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for key, val := range ctx.storages[addr] {
|
||||
for key, val := range ctx.storages[addrHash] {
|
||||
var err error
|
||||
if len(val) == 0 {
|
||||
err = st.Delete(key.Bytes())
|
||||
|
|
@ -206,12 +164,8 @@ func updateAccount(ctx *context, loader TrieLoader, addr common.Address) error {
|
|||
// deleteAccount the account was not present in prev-state, and is expected
|
||||
// to be existent in post-state. Apply the reverse diff and verify if the
|
||||
// account and storage is wiped out correctly.
|
||||
func deleteAccount(ctx *context, loader TrieLoader, addr common.Address) error {
|
||||
func deleteAccount(ctx *context, opener TrieOpener, addrHash common.Hash) error {
|
||||
// The account must be existent in post-state, load the account.
|
||||
h := newHasher()
|
||||
defer h.release()
|
||||
|
||||
addrHash := h.hash(addr.Bytes())
|
||||
blob, err := ctx.accountTrie.Get(addrHash.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -223,11 +177,11 @@ func deleteAccount(ctx *context, loader TrieLoader, addr common.Address) error {
|
|||
if err := rlp.DecodeBytes(blob, &post); err != nil {
|
||||
return err
|
||||
}
|
||||
st, err := loader.OpenStorageTrie(ctx.postRoot, addrHash, post.Root)
|
||||
st, err := opener.OpenStorageTrie(ctx.postRoot, addrHash, post.Root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for key, val := range ctx.storages[addr] {
|
||||
for key, val := range ctx.storages[addrHash] {
|
||||
if len(val) != 0 {
|
||||
return errors.New("expect storage deletion")
|
||||
}
|
||||
|
|
@ -252,22 +206,3 @@ func deleteAccount(ctx *context, loader TrieLoader, addr common.Address) error {
|
|||
// Delete the post-state account from the main trie.
|
||||
return ctx.accountTrie.Delete(addrHash.Bytes())
|
||||
}
|
||||
|
||||
// hasher is used to compute the sha256 hash of the provided data.
|
||||
type hasher struct{ sha crypto.KeccakState }
|
||||
|
||||
var hasherPool = sync.Pool{
|
||||
New: func() interface{} { return &hasher{sha: sha3.NewLegacyKeccak256().(crypto.KeccakState)} },
|
||||
}
|
||||
|
||||
func newHasher() *hasher {
|
||||
return hasherPool.Get().(*hasher)
|
||||
}
|
||||
|
||||
func (h *hasher) hash(data []byte) common.Hash {
|
||||
return crypto.HashData(h.sha, data)
|
||||
}
|
||||
|
||||
func (h *hasher) release() {
|
||||
hasherPool.Put(h)
|
||||
}
|
||||
59
triedb/state/types.go
Normal file
59
triedb/state/types.go
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright 2024 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 "github.com/ethereum/go-ethereum/common"
|
||||
|
||||
// Origin represents the prev-state for a state transition.
|
||||
type Origin struct {
|
||||
// Accounts represents the account data before the state transition, keyed
|
||||
// by the account address. The nil value means the account was not present
|
||||
// before.
|
||||
Accounts map[common.Address][]byte
|
||||
|
||||
// Storages represents the storage data before the state transition, keyed
|
||||
// by the account address and slot key hash. The nil value means the slot
|
||||
// was not present.
|
||||
Storages map[common.Address]map[common.Hash][]byte
|
||||
|
||||
size common.StorageSize // Approximate size of set
|
||||
}
|
||||
|
||||
// NewOrigin constructs the state set with provided data.
|
||||
func NewOrigin(accounts map[common.Address][]byte, storages map[common.Address]map[common.Hash][]byte) *Origin {
|
||||
return &Origin{
|
||||
Accounts: accounts,
|
||||
Storages: storages,
|
||||
}
|
||||
}
|
||||
|
||||
// Size returns the approximate memory size occupied by the set.
|
||||
func (s *Origin) Size() common.StorageSize {
|
||||
if s.size != 0 {
|
||||
return s.size
|
||||
}
|
||||
for _, account := range s.Accounts {
|
||||
s.size += common.StorageSize(common.AddressLength + len(account))
|
||||
}
|
||||
for _, slots := range s.Storages {
|
||||
for _, val := range slots {
|
||||
s.size += common.StorageSize(common.HashLength + len(val))
|
||||
}
|
||||
s.size += common.StorageSize(common.AddressLength)
|
||||
}
|
||||
return s.size
|
||||
}
|
||||
Loading…
Reference in a new issue