mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 06:06:44 +00:00
Merge pull request #11 from berachain/fetch-upstream
This commit is contained in:
commit
31e192db86
53 changed files with 1112 additions and 393 deletions
|
|
@ -2202,36 +2202,38 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("%v", err)
|
Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
cache := &core.CacheConfig{
|
options := &core.BlockChainConfig{
|
||||||
TrieCleanLimit: ethconfig.Defaults.TrieCleanCache,
|
TrieCleanLimit: ethconfig.Defaults.TrieCleanCache,
|
||||||
TrieCleanNoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name),
|
NoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name),
|
||||||
TrieDirtyLimit: ethconfig.Defaults.TrieDirtyCache,
|
TrieDirtyLimit: ethconfig.Defaults.TrieDirtyCache,
|
||||||
TrieDirtyDisabled: ctx.String(GCModeFlag.Name) == "archive",
|
ArchiveMode: ctx.String(GCModeFlag.Name) == "archive",
|
||||||
TrieTimeLimit: ethconfig.Defaults.TrieTimeout,
|
TrieTimeLimit: ethconfig.Defaults.TrieTimeout,
|
||||||
SnapshotLimit: ethconfig.Defaults.SnapshotCache,
|
SnapshotLimit: ethconfig.Defaults.SnapshotCache,
|
||||||
Preimages: ctx.Bool(CachePreimagesFlag.Name),
|
Preimages: ctx.Bool(CachePreimagesFlag.Name),
|
||||||
StateScheme: scheme,
|
StateScheme: scheme,
|
||||||
StateHistory: ctx.Uint64(StateHistoryFlag.Name),
|
StateHistory: ctx.Uint64(StateHistoryFlag.Name),
|
||||||
|
// Disable transaction indexing/unindexing.
|
||||||
|
TxLookupLimit: -1,
|
||||||
}
|
}
|
||||||
if cache.TrieDirtyDisabled && !cache.Preimages {
|
if options.ArchiveMode && !options.Preimages {
|
||||||
cache.Preimages = true
|
options.Preimages = true
|
||||||
log.Info("Enabling recording of key preimages since archive mode is used")
|
log.Info("Enabling recording of key preimages since archive mode is used")
|
||||||
}
|
}
|
||||||
if !ctx.Bool(SnapshotFlag.Name) {
|
if !ctx.Bool(SnapshotFlag.Name) {
|
||||||
cache.SnapshotLimit = 0 // Disabled
|
options.SnapshotLimit = 0 // Disabled
|
||||||
} else if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheSnapshotFlag.Name) {
|
} else if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheSnapshotFlag.Name) {
|
||||||
cache.SnapshotLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheSnapshotFlag.Name) / 100
|
options.SnapshotLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheSnapshotFlag.Name) / 100
|
||||||
}
|
}
|
||||||
// If we're in readonly, do not bother generating snapshot data.
|
// If we're in readonly, do not bother generating snapshot data.
|
||||||
if readonly {
|
if readonly {
|
||||||
cache.SnapshotNoBuild = true
|
options.SnapshotNoBuild = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) {
|
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) {
|
||||||
cache.TrieCleanLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100
|
options.TrieCleanLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100
|
||||||
}
|
}
|
||||||
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) {
|
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) {
|
||||||
cache.TrieDirtyLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100
|
options.TrieDirtyLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100
|
||||||
}
|
}
|
||||||
vmcfg := vm.Config{
|
vmcfg := vm.Config{
|
||||||
EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name),
|
EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name),
|
||||||
|
|
@ -2246,8 +2248,9 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
||||||
vmcfg.Tracer = t
|
vmcfg.Tracer = t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Disable transaction indexing/unindexing by default.
|
options.VmConfig = vmcfg
|
||||||
chain, err := core.NewBlockChain(chainDb, cache, gspec, nil, engine, vmcfg, nil)
|
|
||||||
|
chain, err := core.NewBlockChain(chainDb, gspec, engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("Can't create BlockChain: %v", err)
|
Fatalf("Can't create BlockChain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/internal/era"
|
"github.com/ethereum/go-ethereum/internal/era"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -78,7 +77,7 @@ func TestHistoryImportAndExport(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Initialize BlockChain.
|
// Initialize BlockChain.
|
||||||
chain, err := core.NewBlockChain(db, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil)
|
chain, err := core.NewBlockChain(db, genesis, ethash.NewFaker(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to initialize chain: %v", err)
|
t.Fatalf("unable to initialize chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -167,7 +166,7 @@ func TestHistoryImportAndExport(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
genesis.MustCommit(db2, triedb.NewDatabase(db2, triedb.HashDefaults))
|
genesis.MustCommit(db2, triedb.NewDatabase(db2, triedb.HashDefaults))
|
||||||
imported, err := core.NewBlockChain(db2, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil)
|
imported, err := core.NewBlockChain(db2, genesis, ethash.NewFaker(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to initialize chain: %v", err)
|
t.Fatalf("unable to initialize chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
@ -55,7 +54,7 @@ func TestReimportMirroredState(t *testing.T) {
|
||||||
copy(genspec.ExtraData[extraVanity:], addr[:])
|
copy(genspec.ExtraData[extraVanity:], addr[:])
|
||||||
|
|
||||||
// Generate a batch of blocks, each properly signed
|
// Generate a batch of blocks, each properly signed
|
||||||
chain, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, genspec, nil, engine, vm.Config{}, nil)
|
chain, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), genspec, engine, nil)
|
||||||
defer chain.Stop()
|
defer chain.Stop()
|
||||||
|
|
||||||
_, blocks, _ := core.GenerateChainWithGenesis(genspec, engine, 3, func(i int, block *core.BlockGen) {
|
_, blocks, _ := core.GenerateChainWithGenesis(genspec, engine, 3, func(i int, block *core.BlockGen) {
|
||||||
|
|
@ -87,7 +86,7 @@ func TestReimportMirroredState(t *testing.T) {
|
||||||
}
|
}
|
||||||
// Insert the first two blocks and make sure the chain is valid
|
// Insert the first two blocks and make sure the chain is valid
|
||||||
db = rawdb.NewMemoryDatabase()
|
db = rawdb.NewMemoryDatabase()
|
||||||
chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil)
|
chain, _ = core.NewBlockChain(db, genspec, engine, nil)
|
||||||
defer chain.Stop()
|
defer chain.Stop()
|
||||||
|
|
||||||
if _, err := chain.InsertChain(blocks[:2]); err != nil {
|
if _, err := chain.InsertChain(blocks[:2]); err != nil {
|
||||||
|
|
@ -100,7 +99,7 @@ func TestReimportMirroredState(t *testing.T) {
|
||||||
// Simulate a crash by creating a new chain on top of the database, without
|
// Simulate a crash by creating a new chain on top of the database, without
|
||||||
// flushing the dirty states out. Insert the last block, triggering a sidechain
|
// flushing the dirty states out. Insert the last block, triggering a sidechain
|
||||||
// reimport.
|
// reimport.
|
||||||
chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil)
|
chain, _ = core.NewBlockChain(db, genspec, engine, nil)
|
||||||
defer chain.Stop()
|
defer chain.Stop()
|
||||||
|
|
||||||
if _, err := chain.InsertChain(blocks[2:]); err != nil {
|
if _, err := chain.InsertChain(blocks[2:]); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
@ -458,7 +457,7 @@ func (tt *cliqueTest) run(t *testing.T) {
|
||||||
batches[len(batches)-1] = append(batches[len(batches)-1], block)
|
batches[len(batches)-1] = append(batches[len(batches)-1], block)
|
||||||
}
|
}
|
||||||
// Pass all the headers through clique and ensure tallying succeeds
|
// Pass all the headers through clique and ensure tallying succeeds
|
||||||
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil)
|
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), genesis, engine, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create test chain: %v", err)
|
t.Fatalf("failed to create test chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
||||||
|
|
@ -200,7 +199,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
|
||||||
|
|
||||||
// Time the insertion of the new chain.
|
// Time the insertion of the new chain.
|
||||||
// State and blocks are stored in the same DB.
|
// State and blocks are stored in the same DB.
|
||||||
chainman, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
chainman, _ := NewBlockChain(db, gspec, ethash.NewFaker(), nil)
|
||||||
defer chainman.Stop()
|
defer chainman.Stop()
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
@ -325,9 +324,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
|
||||||
genesis := &Genesis{Config: params.AllEthashProtocolChanges}
|
genesis := &Genesis{Config: params.AllEthashProtocolChanges}
|
||||||
makeChainForBench(db, genesis, full, count)
|
makeChainForBench(db, genesis, full, count)
|
||||||
db.Close()
|
db.Close()
|
||||||
cacheConfig := *defaultCacheConfig
|
options := DefaultConfig().WithArchive(true)
|
||||||
cacheConfig.TrieDirtyDisabled = true
|
|
||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
||||||
|
|
@ -338,7 +335,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
|
||||||
}
|
}
|
||||||
db = rawdb.NewDatabase(pdb)
|
db = rawdb.NewDatabase(pdb)
|
||||||
|
|
||||||
chain, err := NewBlockChain(db, &cacheConfig, genesis, nil, ethash.NewFaker(), vm.Config{}, nil)
|
chain, err := NewBlockChain(db, genesis, ethash.NewFaker(), options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error creating chain: %v", err)
|
b.Fatalf("error creating chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
@ -50,7 +49,8 @@ func testHeaderVerification(t *testing.T, scheme string) {
|
||||||
headers[i] = block.Header()
|
headers[i] = block.Header()
|
||||||
}
|
}
|
||||||
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
|
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
options := DefaultConfig().WithStateScheme(scheme)
|
||||||
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, ethash.NewFaker(), options)
|
||||||
defer chain.Stop()
|
defer chain.Stop()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -166,7 +166,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
|
||||||
postHeaders[i] = block.Header()
|
postHeaders[i] = block.Header()
|
||||||
}
|
}
|
||||||
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
|
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, nil)
|
||||||
defer chain.Stop()
|
defer chain.Stop()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,16 @@ var (
|
||||||
storageUpdateTimer = metrics.NewRegisteredResettingTimer("chain/storage/updates", nil)
|
storageUpdateTimer = metrics.NewRegisteredResettingTimer("chain/storage/updates", nil)
|
||||||
storageCommitTimer = metrics.NewRegisteredResettingTimer("chain/storage/commits", nil)
|
storageCommitTimer = metrics.NewRegisteredResettingTimer("chain/storage/commits", nil)
|
||||||
|
|
||||||
|
accountCacheHitMeter = metrics.NewRegisteredMeter("chain/account/reads/cache/process/hit", nil)
|
||||||
|
accountCacheMissMeter = metrics.NewRegisteredMeter("chain/account/reads/cache/process/miss", nil)
|
||||||
|
storageCacheHitMeter = metrics.NewRegisteredMeter("chain/storage/reads/cache/process/hit", nil)
|
||||||
|
storageCacheMissMeter = metrics.NewRegisteredMeter("chain/storage/reads/cache/process/miss", nil)
|
||||||
|
|
||||||
|
accountCacheHitPrefetchMeter = metrics.NewRegisteredMeter("chain/account/reads/cache/prefetch/hit", nil)
|
||||||
|
accountCacheMissPrefetchMeter = metrics.NewRegisteredMeter("chain/account/reads/cache/prefetch/miss", nil)
|
||||||
|
storageCacheHitPrefetchMeter = metrics.NewRegisteredMeter("chain/storage/reads/cache/prefetch/hit", nil)
|
||||||
|
storageCacheMissPrefetchMeter = metrics.NewRegisteredMeter("chain/storage/reads/cache/prefetch/miss", nil)
|
||||||
|
|
||||||
accountReadSingleTimer = metrics.NewRegisteredResettingTimer("chain/account/single/reads", nil)
|
accountReadSingleTimer = metrics.NewRegisteredResettingTimer("chain/account/single/reads", nil)
|
||||||
storageReadSingleTimer = metrics.NewRegisteredResettingTimer("chain/storage/single/reads", nil)
|
storageReadSingleTimer = metrics.NewRegisteredResettingTimer("chain/storage/single/reads", nil)
|
||||||
|
|
||||||
|
|
@ -149,72 +159,95 @@ const (
|
||||||
BlockChainVersion uint64 = 9
|
BlockChainVersion uint64 = 9
|
||||||
)
|
)
|
||||||
|
|
||||||
// CacheConfig contains the configuration values for the trie database
|
// BlockChainConfig contains the configuration of the BlockChain object.
|
||||||
// and state snapshot these are resident in a blockchain.
|
type BlockChainConfig struct {
|
||||||
type CacheConfig struct {
|
// Trie database related options
|
||||||
TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory
|
TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory
|
||||||
TrieCleanNoPrefetch bool // Whether to disable heuristic state prefetching for followup blocks
|
TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk
|
||||||
TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk
|
TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk
|
||||||
TrieDirtyDisabled bool // Whether to disable trie write caching and GC altogether (archive node)
|
|
||||||
TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk
|
|
||||||
SnapshotLimit int // Memory allowance (MB) to use for caching snapshot entries in memory
|
|
||||||
Preimages bool // Whether to store preimage of trie key to the disk
|
|
||||||
StateHistory uint64 // Number of blocks from head whose state histories are reserved.
|
|
||||||
StateScheme string // Scheme used to store ethereum states and merkle tree nodes on top
|
|
||||||
|
|
||||||
|
Preimages bool // Whether to store preimage of trie key to the disk
|
||||||
|
StateHistory uint64 // Number of blocks from head whose state histories are reserved.
|
||||||
|
StateScheme string // Scheme used to store ethereum states and merkle tree nodes on top
|
||||||
|
ArchiveMode bool // Whether to enable the archive mode
|
||||||
|
|
||||||
|
// State snapshot related options
|
||||||
|
SnapshotLimit int // Memory allowance (MB) to use for caching snapshot entries in memory
|
||||||
SnapshotNoBuild bool // Whether the background generation is allowed
|
SnapshotNoBuild bool // Whether the background generation is allowed
|
||||||
SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it
|
SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it
|
||||||
|
|
||||||
// This defines the cutoff block for history expiry.
|
// This defines the cutoff block for history expiry.
|
||||||
// Blocks before this number may be unavailable in the chain database.
|
// Blocks before this number may be unavailable in the chain database.
|
||||||
ChainHistoryMode history.HistoryMode
|
ChainHistoryMode history.HistoryMode
|
||||||
|
|
||||||
|
// Misc options
|
||||||
|
NoPrefetch bool // Whether to disable heuristic state prefetching when processing blocks
|
||||||
|
Overrides *ChainOverrides // Optional chain config overrides
|
||||||
|
VmConfig vm.Config // Config options for the EVM Interpreter
|
||||||
|
|
||||||
|
// TxLookupLimit specifies the maximum number of blocks from head for which
|
||||||
|
// transaction hashes will be indexed.
|
||||||
|
//
|
||||||
|
// If the value is zero, all transactions of the entire chain will be indexed.
|
||||||
|
// If the value is -1, indexing is disabled.
|
||||||
|
TxLookupLimit int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultConfig returns the default config.
|
||||||
|
// Note the returned object is safe to modify!
|
||||||
|
func DefaultConfig() *BlockChainConfig {
|
||||||
|
return &BlockChainConfig{
|
||||||
|
TrieCleanLimit: 256,
|
||||||
|
TrieDirtyLimit: 256,
|
||||||
|
TrieTimeLimit: 5 * time.Minute,
|
||||||
|
StateScheme: rawdb.HashScheme,
|
||||||
|
SnapshotLimit: 256,
|
||||||
|
SnapshotWait: true,
|
||||||
|
ChainHistoryMode: history.KeepAll,
|
||||||
|
// Transaction indexing is disabled by default.
|
||||||
|
// This is appropriate for most unit tests.
|
||||||
|
TxLookupLimit: -1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithArchive enabled/disables archive mode on the config.
|
||||||
|
func (cfg BlockChainConfig) WithArchive(on bool) *BlockChainConfig {
|
||||||
|
cfg.ArchiveMode = on
|
||||||
|
return &cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithStateScheme sets the state storage scheme on the config.
|
||||||
|
func (cfg BlockChainConfig) WithStateScheme(scheme string) *BlockChainConfig {
|
||||||
|
cfg.StateScheme = scheme
|
||||||
|
return &cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
// triedbConfig derives the configures for trie database.
|
// triedbConfig derives the configures for trie database.
|
||||||
func (c *CacheConfig) triedbConfig(isVerkle bool) *triedb.Config {
|
func (cfg *BlockChainConfig) triedbConfig(isVerkle bool) *triedb.Config {
|
||||||
config := &triedb.Config{
|
config := &triedb.Config{
|
||||||
Preimages: c.Preimages,
|
Preimages: cfg.Preimages,
|
||||||
IsVerkle: isVerkle,
|
IsVerkle: isVerkle,
|
||||||
}
|
}
|
||||||
if c.StateScheme == rawdb.HashScheme {
|
if cfg.StateScheme == rawdb.HashScheme {
|
||||||
config.HashDB = &hashdb.Config{
|
config.HashDB = &hashdb.Config{
|
||||||
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
|
CleanCacheSize: cfg.TrieCleanLimit * 1024 * 1024,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if c.StateScheme == rawdb.PathScheme {
|
if cfg.StateScheme == rawdb.PathScheme {
|
||||||
config.PathDB = &pathdb.Config{
|
config.PathDB = &pathdb.Config{
|
||||||
StateHistory: c.StateHistory,
|
StateHistory: cfg.StateHistory,
|
||||||
TrieCleanSize: c.TrieCleanLimit * 1024 * 1024,
|
TrieCleanSize: cfg.TrieCleanLimit * 1024 * 1024,
|
||||||
StateCleanSize: c.SnapshotLimit * 1024 * 1024,
|
StateCleanSize: cfg.SnapshotLimit * 1024 * 1024,
|
||||||
|
|
||||||
// TODO(rjl493456442): The write buffer represents the memory limit used
|
// TODO(rjl493456442): The write buffer represents the memory limit used
|
||||||
// for flushing both trie data and state data to disk. The config name
|
// for flushing both trie data and state data to disk. The config name
|
||||||
// should be updated to eliminate the confusion.
|
// should be updated to eliminate the confusion.
|
||||||
WriteBufferSize: c.TrieDirtyLimit * 1024 * 1024,
|
WriteBufferSize: cfg.TrieDirtyLimit * 1024 * 1024,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultCacheConfig are the default caching values if none are specified by the
|
|
||||||
// user (also used during testing).
|
|
||||||
var defaultCacheConfig = &CacheConfig{
|
|
||||||
TrieCleanLimit: 256,
|
|
||||||
TrieDirtyLimit: 256,
|
|
||||||
TrieTimeLimit: 5 * time.Minute,
|
|
||||||
SnapshotLimit: 256,
|
|
||||||
SnapshotWait: true,
|
|
||||||
StateScheme: rawdb.HashScheme,
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultCacheConfigWithScheme returns a deep copied default cache config with
|
|
||||||
// a provided trie node scheme.
|
|
||||||
func DefaultCacheConfigWithScheme(scheme string) *CacheConfig {
|
|
||||||
config := *defaultCacheConfig
|
|
||||||
config.StateScheme = scheme
|
|
||||||
return &config
|
|
||||||
}
|
|
||||||
|
|
||||||
// txLookup is wrapper over transaction lookup along with the corresponding
|
// txLookup is wrapper over transaction lookup along with the corresponding
|
||||||
// transaction object.
|
// transaction object.
|
||||||
type txLookup struct {
|
type txLookup struct {
|
||||||
|
|
@ -238,7 +271,7 @@ type txLookup struct {
|
||||||
// canonical chain.
|
// canonical chain.
|
||||||
type BlockChain struct {
|
type BlockChain struct {
|
||||||
chainConfig *params.ChainConfig // Chain & network configuration
|
chainConfig *params.ChainConfig // Chain & network configuration
|
||||||
cacheConfig *CacheConfig // Cache configuration for pruning
|
cfg *BlockChainConfig // Blockchain configuration
|
||||||
|
|
||||||
db ethdb.Database // Low level persistent database to store final content in
|
db ethdb.Database // Low level persistent database to store final content in
|
||||||
snaps *snapshot.Tree // Snapshot tree for fast trie leaf access
|
snaps *snapshot.Tree // Snapshot tree for fast trie leaf access
|
||||||
|
|
@ -285,7 +318,6 @@ type BlockChain struct {
|
||||||
validator Validator // Block and state validator interface
|
validator Validator // Block and state validator interface
|
||||||
prefetcher Prefetcher
|
prefetcher Prefetcher
|
||||||
processor Processor // Block transaction processor interface
|
processor Processor // Block transaction processor interface
|
||||||
vmConfig vm.Config
|
|
||||||
logger *tracing.Hooks
|
logger *tracing.Hooks
|
||||||
|
|
||||||
lastForkReadyAlert time.Time // Last time there was a fork readiness print out
|
lastForkReadyAlert time.Time // Last time there was a fork readiness print out
|
||||||
|
|
@ -294,22 +326,23 @@ type BlockChain struct {
|
||||||
// NewBlockChain returns a fully initialised block chain using information
|
// NewBlockChain returns a fully initialised block chain using information
|
||||||
// available in the database. It initialises the default Ethereum Validator
|
// available in the database. It initialises the default Ethereum Validator
|
||||||
// and Processor.
|
// and Processor.
|
||||||
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis, overrides *ChainOverrides, engine consensus.Engine, vmConfig vm.Config, txLookupLimit *uint64) (*BlockChain, error) {
|
func NewBlockChain(db ethdb.Database, genesis *Genesis, engine consensus.Engine, cfg *BlockChainConfig) (*BlockChain, error) {
|
||||||
if cacheConfig == nil {
|
if cfg == nil {
|
||||||
cacheConfig = defaultCacheConfig
|
cfg = DefaultConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open trie database with provided config
|
// Open trie database with provided config
|
||||||
enableVerkle, err := EnableVerkleAtGenesis(db, genesis)
|
enableVerkle, err := EnableVerkleAtGenesis(db, genesis)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(enableVerkle))
|
triedb := triedb.NewDatabase(db, cfg.triedbConfig(enableVerkle))
|
||||||
|
|
||||||
// Write the supplied genesis to the database if it has not been initialized
|
// Write the supplied genesis to the database if it has not been initialized
|
||||||
// yet. The corresponding chain config will be returned, either from the
|
// yet. The corresponding chain config will be returned, either from the
|
||||||
// provided genesis or from the locally stored configuration if the genesis
|
// provided genesis or from the locally stored configuration if the genesis
|
||||||
// has already been initialized.
|
// has already been initialized.
|
||||||
chainConfig, genesisHash, compatErr, err := SetupGenesisBlockWithOverride(db, triedb, genesis, overrides)
|
chainConfig, genesisHash, compatErr, err := SetupGenesisBlockWithOverride(db, triedb, genesis, cfg.Overrides)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -323,7 +356,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||||
|
|
||||||
bc := &BlockChain{
|
bc := &BlockChain{
|
||||||
chainConfig: chainConfig,
|
chainConfig: chainConfig,
|
||||||
cacheConfig: cacheConfig,
|
cfg: cfg,
|
||||||
db: db,
|
db: db,
|
||||||
triedb: triedb,
|
triedb: triedb,
|
||||||
triegc: prque.New[int64, common.Hash](nil),
|
triegc: prque.New[int64, common.Hash](nil),
|
||||||
|
|
@ -334,14 +367,13 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||||
blockCache: lru.NewCache[common.Hash, *types.Block](blockCacheLimit),
|
blockCache: lru.NewCache[common.Hash, *types.Block](blockCacheLimit),
|
||||||
txLookupCache: lru.NewCache[common.Hash, txLookup](txLookupCacheLimit),
|
txLookupCache: lru.NewCache[common.Hash, txLookup](txLookupCacheLimit),
|
||||||
engine: engine,
|
engine: engine,
|
||||||
vmConfig: vmConfig,
|
logger: cfg.VmConfig.Tracer,
|
||||||
logger: vmConfig.Tracer,
|
|
||||||
}
|
}
|
||||||
bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.insertStopped)
|
bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.insertStopped)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit))
|
bc.flushInterval.Store(int64(cfg.TrieTimeLimit))
|
||||||
bc.statedb = state.NewDatabase(bc.triedb, nil)
|
bc.statedb = state.NewDatabase(bc.triedb, nil)
|
||||||
bc.validator = NewBlockValidator(chainConfig, bc)
|
bc.validator = NewBlockValidator(chainConfig, bc)
|
||||||
bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc)
|
bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc)
|
||||||
|
|
@ -390,7 +422,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||||
// Note it's unnecessary in path mode which always keep trie data and
|
// Note it's unnecessary in path mode which always keep trie data and
|
||||||
// state data consistent.
|
// state data consistent.
|
||||||
var diskRoot common.Hash
|
var diskRoot common.Hash
|
||||||
if bc.cacheConfig.SnapshotLimit > 0 && bc.cacheConfig.StateScheme == rawdb.HashScheme {
|
if bc.cfg.SnapshotLimit > 0 && bc.cfg.StateScheme == rawdb.HashScheme {
|
||||||
diskRoot = rawdb.ReadSnapshotRoot(bc.db)
|
diskRoot = rawdb.ReadSnapshotRoot(bc.db)
|
||||||
}
|
}
|
||||||
if diskRoot != (common.Hash{}) {
|
if diskRoot != (common.Hash{}) {
|
||||||
|
|
@ -477,8 +509,8 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start tx indexer if it's enabled.
|
// Start tx indexer if it's enabled.
|
||||||
if txLookupLimit != nil {
|
if bc.cfg.TxLookupLimit >= 0 {
|
||||||
bc.txIndexer = newTxIndexer(*txLookupLimit, bc)
|
bc.txIndexer = newTxIndexer(uint64(bc.cfg.TxLookupLimit), bc)
|
||||||
}
|
}
|
||||||
return bc, nil
|
return bc, nil
|
||||||
}
|
}
|
||||||
|
|
@ -486,11 +518,11 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||||
func (bc *BlockChain) setupSnapshot() {
|
func (bc *BlockChain) setupSnapshot() {
|
||||||
// Short circuit if the chain is established with path scheme, as the
|
// Short circuit if the chain is established with path scheme, as the
|
||||||
// state snapshot has been integrated into path database natively.
|
// state snapshot has been integrated into path database natively.
|
||||||
if bc.cacheConfig.StateScheme == rawdb.PathScheme {
|
if bc.cfg.StateScheme == rawdb.PathScheme {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Load any existing snapshot, regenerating it if loading failed
|
// Load any existing snapshot, regenerating it if loading failed
|
||||||
if bc.cacheConfig.SnapshotLimit > 0 {
|
if bc.cfg.SnapshotLimit > 0 {
|
||||||
// If the chain was rewound past the snapshot persistent layer (causing
|
// If the chain was rewound past the snapshot persistent layer (causing
|
||||||
// a recovery block number to be persisted to disk), check if we're still
|
// a recovery block number to be persisted to disk), check if we're still
|
||||||
// in recovery mode and in that case, don't invalidate the snapshot on a
|
// in recovery mode and in that case, don't invalidate the snapshot on a
|
||||||
|
|
@ -502,10 +534,10 @@ func (bc *BlockChain) setupSnapshot() {
|
||||||
recover = true
|
recover = true
|
||||||
}
|
}
|
||||||
snapconfig := snapshot.Config{
|
snapconfig := snapshot.Config{
|
||||||
CacheSize: bc.cacheConfig.SnapshotLimit,
|
CacheSize: bc.cfg.SnapshotLimit,
|
||||||
Recovery: recover,
|
Recovery: recover,
|
||||||
NoBuild: bc.cacheConfig.SnapshotNoBuild,
|
NoBuild: bc.cfg.SnapshotNoBuild,
|
||||||
AsyncBuild: !bc.cacheConfig.SnapshotWait,
|
AsyncBuild: !bc.cfg.SnapshotWait,
|
||||||
}
|
}
|
||||||
bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root)
|
bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root)
|
||||||
|
|
||||||
|
|
@ -629,7 +661,7 @@ func (bc *BlockChain) loadLastState() error {
|
||||||
func (bc *BlockChain) initializeHistoryPruning(latest uint64) error {
|
func (bc *BlockChain) initializeHistoryPruning(latest uint64) error {
|
||||||
freezerTail, _ := bc.db.Tail()
|
freezerTail, _ := bc.db.Tail()
|
||||||
|
|
||||||
switch bc.cacheConfig.ChainHistoryMode {
|
switch bc.cfg.ChainHistoryMode {
|
||||||
case history.KeepAll:
|
case history.KeepAll:
|
||||||
if freezerTail == 0 {
|
if freezerTail == 0 {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -650,7 +682,7 @@ func (bc *BlockChain) initializeHistoryPruning(latest uint64) error {
|
||||||
// postmerge directly on an existing DB. We could just trigger the pruning
|
// postmerge directly on an existing DB. We could just trigger the pruning
|
||||||
// here, but it'd be a bit dangerous since they may not have intended this
|
// here, but it'd be a bit dangerous since they may not have intended this
|
||||||
// action to happen. So just tell them how to do it.
|
// action to happen. So just tell them how to do it.
|
||||||
log.Error(fmt.Sprintf("Chain history mode is configured as %q, but database is not pruned.", bc.cacheConfig.ChainHistoryMode.String()))
|
log.Error(fmt.Sprintf("Chain history mode is configured as %q, but database is not pruned.", bc.cfg.ChainHistoryMode.String()))
|
||||||
log.Error(fmt.Sprintf("Run 'geth prune-history' to prune pre-merge history."))
|
log.Error(fmt.Sprintf("Run 'geth prune-history' to prune pre-merge history."))
|
||||||
return fmt.Errorf("history pruning requested via configuration")
|
return fmt.Errorf("history pruning requested via configuration")
|
||||||
}
|
}
|
||||||
|
|
@ -666,7 +698,7 @@ func (bc *BlockChain) initializeHistoryPruning(latest uint64) error {
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("invalid history mode: %d", bc.cacheConfig.ChainHistoryMode)
|
return fmt.Errorf("invalid history mode: %d", bc.cfg.ChainHistoryMode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1240,7 +1272,7 @@ func (bc *BlockChain) Stop() {
|
||||||
// - HEAD: So we don't need to reprocess any blocks in the general case
|
// - HEAD: So we don't need to reprocess any blocks in the general case
|
||||||
// - HEAD-1: So we don't do large reorgs if our HEAD becomes an uncle
|
// - HEAD-1: So we don't do large reorgs if our HEAD becomes an uncle
|
||||||
// - HEAD-127: So we have a hard limit on the number of blocks reexecuted
|
// - HEAD-127: So we have a hard limit on the number of blocks reexecuted
|
||||||
if !bc.cacheConfig.TrieDirtyDisabled {
|
if !bc.cfg.ArchiveMode {
|
||||||
triedb := bc.triedb
|
triedb := bc.triedb
|
||||||
|
|
||||||
for _, offset := range []uint64{0, 1, state.TriesInMemory - 1} {
|
for _, offset := range []uint64{0, 1, state.TriesInMemory - 1} {
|
||||||
|
|
@ -1546,7 +1578,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// If we're running an archive node, always flush
|
// If we're running an archive node, always flush
|
||||||
if bc.cacheConfig.TrieDirtyDisabled {
|
if bc.cfg.ArchiveMode {
|
||||||
return bc.triedb.Commit(root, false)
|
return bc.triedb.Commit(root, false)
|
||||||
}
|
}
|
||||||
// Full but not archive node, do proper garbage collection
|
// Full but not archive node, do proper garbage collection
|
||||||
|
|
@ -1561,7 +1593,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
||||||
// If we exceeded our memory allowance, flush matured singleton nodes to disk
|
// If we exceeded our memory allowance, flush matured singleton nodes to disk
|
||||||
var (
|
var (
|
||||||
_, nodes, imgs = bc.triedb.Size() // all memory is contained within the nodes return for hashdb
|
_, nodes, imgs = bc.triedb.Size() // all memory is contained within the nodes return for hashdb
|
||||||
limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024
|
limit = common.StorageSize(bc.cfg.TrieDirtyLimit) * 1024 * 1024
|
||||||
)
|
)
|
||||||
if nodes > limit || imgs > 4*1024*1024 {
|
if nodes > limit || imgs > 4*1024*1024 {
|
||||||
bc.triedb.Cap(limit - ethdb.IdealBatchSize)
|
bc.triedb.Cap(limit - ethdb.IdealBatchSize)
|
||||||
|
|
@ -1911,7 +1943,7 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s
|
||||||
)
|
)
|
||||||
defer interrupt.Store(true) // terminate the prefetch at the end
|
defer interrupt.Store(true) // terminate the prefetch at the end
|
||||||
|
|
||||||
if bc.cacheConfig.TrieCleanNoPrefetch {
|
if bc.cfg.NoPrefetch {
|
||||||
statedb, err = state.New(parentRoot, bc.statedb)
|
statedb, err = state.New(parentRoot, bc.statedb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -1922,21 +1954,35 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s
|
||||||
//
|
//
|
||||||
// Note: the main processor and prefetcher share the same reader with a local
|
// Note: the main processor and prefetcher share the same reader with a local
|
||||||
// cache for mitigating the overhead of state access.
|
// cache for mitigating the overhead of state access.
|
||||||
reader, err := bc.statedb.ReaderWithCache(parentRoot)
|
prefetch, process, err := bc.statedb.ReadersWithCacheStats(parentRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
throwaway, err := state.NewWithReader(parentRoot, bc.statedb, reader)
|
throwaway, err := state.NewWithReader(parentRoot, bc.statedb, prefetch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
statedb, err = state.NewWithReader(parentRoot, bc.statedb, reader)
|
statedb, err = state.NewWithReader(parentRoot, bc.statedb, process)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// Upload the statistics of reader at the end
|
||||||
|
defer func() {
|
||||||
|
stats := prefetch.GetStats()
|
||||||
|
accountCacheHitPrefetchMeter.Mark(stats.AccountHit)
|
||||||
|
accountCacheMissPrefetchMeter.Mark(stats.AccountMiss)
|
||||||
|
storageCacheHitPrefetchMeter.Mark(stats.StorageHit)
|
||||||
|
storageCacheMissPrefetchMeter.Mark(stats.StorageMiss)
|
||||||
|
stats = process.GetStats()
|
||||||
|
accountCacheHitMeter.Mark(stats.AccountHit)
|
||||||
|
accountCacheMissMeter.Mark(stats.AccountMiss)
|
||||||
|
storageCacheHitMeter.Mark(stats.StorageHit)
|
||||||
|
storageCacheMissMeter.Mark(stats.StorageMiss)
|
||||||
|
}()
|
||||||
|
|
||||||
go func(start time.Time, throwaway *state.StateDB, block *types.Block) {
|
go func(start time.Time, throwaway *state.StateDB, block *types.Block) {
|
||||||
// Disable tracing for prefetcher executions.
|
// Disable tracing for prefetcher executions.
|
||||||
vmCfg := bc.vmConfig
|
vmCfg := bc.cfg.VmConfig
|
||||||
vmCfg.Tracer = nil
|
vmCfg.Tracer = nil
|
||||||
bc.prefetcher.Prefetch(block, throwaway, vmCfg, &interrupt)
|
bc.prefetcher.Prefetch(block, throwaway, vmCfg, &interrupt)
|
||||||
|
|
||||||
|
|
@ -1955,7 +2001,7 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s
|
||||||
// Generate witnesses either if we're self-testing, or if it's the
|
// Generate witnesses either if we're self-testing, or if it's the
|
||||||
// only block being inserted. A bit crude, but witnesses are huge,
|
// only block being inserted. A bit crude, but witnesses are huge,
|
||||||
// so we refuse to make an entire chain of them.
|
// so we refuse to make an entire chain of them.
|
||||||
if bc.vmConfig.StatelessSelfValidation || makeWitness {
|
if bc.cfg.VmConfig.StatelessSelfValidation || makeWitness {
|
||||||
witness, err = stateless.NewWitness(block.Header(), bc)
|
witness, err = stateless.NewWitness(block.Header(), bc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -1980,7 +2026,7 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s
|
||||||
|
|
||||||
// Process block using the parent state as reference point
|
// Process block using the parent state as reference point
|
||||||
pstart := time.Now()
|
pstart := time.Now()
|
||||||
res, err := bc.processor.Process(block, statedb, bc.vmConfig)
|
res, err := bc.processor.Process(block, statedb, bc.cfg.VmConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
bc.reportBlock(block, res, err)
|
bc.reportBlock(block, res, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -2000,7 +2046,7 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s
|
||||||
// witness builder/runner, which would otherwise be impossible due to the
|
// witness builder/runner, which would otherwise be impossible due to the
|
||||||
// various invalid chain states/behaviors being contained in those tests.
|
// various invalid chain states/behaviors being contained in those tests.
|
||||||
xvstart := time.Now()
|
xvstart := time.Now()
|
||||||
if witness := statedb.Witness(); witness != nil && bc.vmConfig.StatelessSelfValidation {
|
if witness := statedb.Witness(); witness != nil && bc.cfg.VmConfig.StatelessSelfValidation {
|
||||||
log.Warn("Running stateless self-validation", "block", block.Number(), "hash", block.Hash())
|
log.Warn("Running stateless self-validation", "block", block.Number(), "hash", block.Hash())
|
||||||
|
|
||||||
// Remove critical computed fields from the block to force true recalculation
|
// Remove critical computed fields from the block to force true recalculation
|
||||||
|
|
@ -2011,7 +2057,7 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s
|
||||||
task := types.NewBlockWithHeader(context).WithBody(*block.Body())
|
task := types.NewBlockWithHeader(context).WithBody(*block.Body())
|
||||||
|
|
||||||
// Run the stateless self-cross-validation
|
// Run the stateless self-cross-validation
|
||||||
crossStateRoot, crossReceiptRoot, err := ExecuteStateless(bc.chainConfig, bc.vmConfig, task, witness)
|
crossStateRoot, crossReceiptRoot, err := ExecuteStateless(bc.chainConfig, bc.cfg.VmConfig, task, witness)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("stateless self-validation failed: %v", err)
|
return nil, fmt.Errorf("stateless self-validation failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -408,7 +408,7 @@ func (bc *BlockChain) Genesis() *types.Block {
|
||||||
|
|
||||||
// GetVMConfig returns the block chain VM config.
|
// GetVMConfig returns the block chain VM config.
|
||||||
func (bc *BlockChain) GetVMConfig() *vm.Config {
|
func (bc *BlockChain) GetVMConfig() *vm.Config {
|
||||||
return &bc.vmConfig
|
return &bc.cfg.VmConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// TxIndexProgress returns the transaction indexing progress.
|
// TxIndexProgress returns the transaction indexing progress.
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
@ -1782,20 +1781,21 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
|
||||||
Config: params.AllEthashProtocolChanges,
|
Config: params.AllEthashProtocolChanges,
|
||||||
}
|
}
|
||||||
engine = ethash.NewFullFaker()
|
engine = ethash.NewFullFaker()
|
||||||
config = &CacheConfig{
|
option = &BlockChainConfig{
|
||||||
TrieCleanLimit: 256,
|
TrieCleanLimit: 256,
|
||||||
TrieDirtyLimit: 256,
|
TrieDirtyLimit: 256,
|
||||||
TrieTimeLimit: 5 * time.Minute,
|
TrieTimeLimit: 5 * time.Minute,
|
||||||
SnapshotLimit: 0, // Disable snapshot by default
|
SnapshotLimit: 0, // disable snapshot by default
|
||||||
|
TxLookupLimit: -1, // disable tx indexing
|
||||||
StateScheme: scheme,
|
StateScheme: scheme,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
defer engine.Close()
|
defer engine.Close()
|
||||||
if snapshots && scheme == rawdb.HashScheme {
|
if snapshots && scheme == rawdb.HashScheme {
|
||||||
config.SnapshotLimit = 256
|
option.SnapshotLimit = 256
|
||||||
config.SnapshotWait = true
|
option.SnapshotWait = true
|
||||||
}
|
}
|
||||||
chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(db, gspec, engine, option)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create chain: %v", err)
|
t.Fatalf("Failed to create chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1860,7 +1860,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
newChain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil)
|
newChain, err := NewBlockChain(db, gspec, engine, option)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1931,9 +1931,10 @@ func testIssue23496(t *testing.T, scheme string) {
|
||||||
Config: params.TestChainConfig,
|
Config: params.TestChainConfig,
|
||||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||||
}
|
}
|
||||||
engine = ethash.NewFullFaker()
|
engine = ethash.NewFullFaker()
|
||||||
|
options = DefaultConfig().WithStateScheme(scheme)
|
||||||
)
|
)
|
||||||
chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(db, gspec, engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create chain: %v", err)
|
t.Fatalf("Failed to create chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1985,7 +1986,7 @@ func testIssue23496(t *testing.T, scheme string) {
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
chain, err = NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil)
|
chain, err = NewBlockChain(db, gspec, engine, DefaultConfig().WithStateScheme(scheme))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/triedb"
|
"github.com/ethereum/go-ethereum/triedb"
|
||||||
|
|
@ -1985,20 +1984,21 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
|
||||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||||
Config: params.AllEthashProtocolChanges,
|
Config: params.AllEthashProtocolChanges,
|
||||||
}
|
}
|
||||||
engine = ethash.NewFullFaker()
|
engine = ethash.NewFullFaker()
|
||||||
config = &CacheConfig{
|
options = &BlockChainConfig{
|
||||||
TrieCleanLimit: 256,
|
TrieCleanLimit: 256,
|
||||||
TrieDirtyLimit: 256,
|
TrieDirtyLimit: 256,
|
||||||
TrieTimeLimit: 5 * time.Minute,
|
TrieTimeLimit: 5 * time.Minute,
|
||||||
SnapshotLimit: 0, // Disable snapshot
|
SnapshotLimit: 0, // disable snapshot
|
||||||
|
TxLookupLimit: -1, // disable tx indexing
|
||||||
StateScheme: scheme,
|
StateScheme: scheme,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if snapshots {
|
if snapshots {
|
||||||
config.SnapshotLimit = 256
|
options.SnapshotLimit = 256
|
||||||
config.SnapshotWait = true
|
options.SnapshotWait = true
|
||||||
}
|
}
|
||||||
chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(db, gspec, engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create chain: %v", err)
|
t.Fatalf("Failed to create chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -82,7 +81,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
|
||||||
}
|
}
|
||||||
engine = ethash.NewFullFaker()
|
engine = ethash.NewFullFaker()
|
||||||
)
|
)
|
||||||
chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(basic.scheme), gspec, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(db, gspec, engine, DefaultConfig().WithStateScheme(basic.scheme))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create chain: %v", err)
|
t.Fatalf("Failed to create chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -233,7 +232,7 @@ func (snaptest *snapshotTest) test(t *testing.T) {
|
||||||
|
|
||||||
// Restart the chain normally
|
// Restart the chain normally
|
||||||
chain.Stop()
|
chain.Stop()
|
||||||
newchain, err := NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)
|
newchain, err := NewBlockChain(snaptest.db, snaptest.gspec, snaptest.engine, DefaultConfig().WithStateScheme(snaptest.scheme))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -275,13 +274,13 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) {
|
||||||
// the crash, we do restart twice here: one after the crash and one
|
// the crash, we do restart twice here: one after the crash and one
|
||||||
// after the normal stop. It's used to ensure the broken snapshot
|
// after the normal stop. It's used to ensure the broken snapshot
|
||||||
// can be detected all the time.
|
// can be detected all the time.
|
||||||
newchain, err := NewBlockChain(newdb, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)
|
newchain, err := NewBlockChain(newdb, snaptest.gspec, snaptest.engine, DefaultConfig().WithStateScheme(snaptest.scheme))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
newchain.Stop()
|
newchain.Stop()
|
||||||
|
|
||||||
newchain, err = NewBlockChain(newdb, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)
|
newchain, err = NewBlockChain(newdb, snaptest.gspec, snaptest.engine, DefaultConfig().WithStateScheme(snaptest.scheme))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -311,14 +310,15 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) {
|
||||||
gappedBlocks, _ := GenerateChain(snaptest.gspec.Config, blocks[len(blocks)-1], snaptest.engine, snaptest.genDb, snaptest.gapped, func(i int, b *BlockGen) {})
|
gappedBlocks, _ := GenerateChain(snaptest.gspec.Config, blocks[len(blocks)-1], snaptest.engine, snaptest.genDb, snaptest.gapped, func(i int, b *BlockGen) {})
|
||||||
|
|
||||||
// Insert a few more blocks without enabling snapshot
|
// Insert a few more blocks without enabling snapshot
|
||||||
var cacheConfig = &CacheConfig{
|
var options = &BlockChainConfig{
|
||||||
TrieCleanLimit: 256,
|
TrieCleanLimit: 256,
|
||||||
TrieDirtyLimit: 256,
|
TrieDirtyLimit: 256,
|
||||||
TrieTimeLimit: 5 * time.Minute,
|
TrieTimeLimit: 5 * time.Minute,
|
||||||
SnapshotLimit: 0,
|
SnapshotLimit: 0,
|
||||||
StateScheme: snaptest.scheme,
|
StateScheme: snaptest.scheme,
|
||||||
|
TxLookupLimit: -1,
|
||||||
}
|
}
|
||||||
newchain, err := NewBlockChain(snaptest.db, cacheConfig, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)
|
newchain, err := NewBlockChain(snaptest.db, snaptest.gspec, snaptest.engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -326,7 +326,8 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) {
|
||||||
newchain.Stop()
|
newchain.Stop()
|
||||||
|
|
||||||
// Restart the chain with enabling the snapshot
|
// Restart the chain with enabling the snapshot
|
||||||
newchain, err = NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)
|
options = DefaultConfig().WithStateScheme(snaptest.scheme)
|
||||||
|
newchain, err = NewBlockChain(snaptest.db, snaptest.gspec, snaptest.engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -354,7 +355,7 @@ func (snaptest *setHeadSnapshotTest) test(t *testing.T) {
|
||||||
chain.SetHead(snaptest.setHead)
|
chain.SetHead(snaptest.setHead)
|
||||||
chain.Stop()
|
chain.Stop()
|
||||||
|
|
||||||
newchain, err := NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)
|
newchain, err := NewBlockChain(snaptest.db, snaptest.gspec, snaptest.engine, DefaultConfig().WithStateScheme(snaptest.scheme))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -383,14 +384,15 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
|
||||||
// and state committed.
|
// and state committed.
|
||||||
chain.Stop()
|
chain.Stop()
|
||||||
|
|
||||||
config := &CacheConfig{
|
config := &BlockChainConfig{
|
||||||
TrieCleanLimit: 256,
|
TrieCleanLimit: 256,
|
||||||
TrieDirtyLimit: 256,
|
TrieDirtyLimit: 256,
|
||||||
TrieTimeLimit: 5 * time.Minute,
|
TrieTimeLimit: 5 * time.Minute,
|
||||||
SnapshotLimit: 0,
|
SnapshotLimit: 0,
|
||||||
StateScheme: snaptest.scheme,
|
StateScheme: snaptest.scheme,
|
||||||
|
TxLookupLimit: -1,
|
||||||
}
|
}
|
||||||
newchain, err := NewBlockChain(snaptest.db, config, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)
|
newchain, err := NewBlockChain(snaptest.db, snaptest.gspec, snaptest.engine, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -399,15 +401,16 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
|
||||||
newchain.Stop()
|
newchain.Stop()
|
||||||
|
|
||||||
// Restart the chain, the wiper should start working
|
// Restart the chain, the wiper should start working
|
||||||
config = &CacheConfig{
|
config = &BlockChainConfig{
|
||||||
TrieCleanLimit: 256,
|
TrieCleanLimit: 256,
|
||||||
TrieDirtyLimit: 256,
|
TrieDirtyLimit: 256,
|
||||||
TrieTimeLimit: 5 * time.Minute,
|
TrieTimeLimit: 5 * time.Minute,
|
||||||
SnapshotLimit: 256,
|
SnapshotLimit: 256,
|
||||||
SnapshotWait: false, // Don't wait rebuild
|
SnapshotWait: false, // Don't wait rebuild
|
||||||
StateScheme: snaptest.scheme,
|
StateScheme: snaptest.scheme,
|
||||||
|
TxLookupLimit: -1,
|
||||||
}
|
}
|
||||||
tmp, err := NewBlockChain(snaptest.db, config, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)
|
tmp, err := NewBlockChain(snaptest.db, snaptest.gspec, snaptest.engine, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -416,7 +419,7 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
|
||||||
tmp.triedb.Close()
|
tmp.triedb.Close()
|
||||||
tmp.stopWithoutSaving()
|
tmp.stopWithoutSaving()
|
||||||
|
|
||||||
newchain, err = NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)
|
newchain, err = NewBlockChain(snaptest.db, snaptest.gspec, snaptest.engine, DefaultConfig().WithStateScheme(snaptest.scheme))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,8 @@ func newCanonical(engine consensus.Engine, n int, full bool, scheme string) (eth
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
// Initialize a fresh chain with only a genesis block
|
// Initialize a fresh chain with only a genesis block
|
||||||
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil)
|
options := DefaultConfig().WithStateScheme(scheme)
|
||||||
|
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), genesis, engine, options)
|
||||||
|
|
||||||
// Create and inject the requested chain
|
// Create and inject the requested chain
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
|
|
@ -723,7 +724,7 @@ func testFastVsFullChains(t *testing.T, scheme string) {
|
||||||
})
|
})
|
||||||
// Import the chain as an archive node for the comparison baseline
|
// Import the chain as an archive node for the comparison baseline
|
||||||
archiveDb := rawdb.NewMemoryDatabase()
|
archiveDb := rawdb.NewMemoryDatabase()
|
||||||
archive, _ := NewBlockChain(archiveDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
archive, _ := NewBlockChain(archiveDb, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme))
|
||||||
defer archive.Stop()
|
defer archive.Stop()
|
||||||
|
|
||||||
if n, err := archive.InsertChain(blocks); err != nil {
|
if n, err := archive.InsertChain(blocks); err != nil {
|
||||||
|
|
@ -731,7 +732,7 @@ func testFastVsFullChains(t *testing.T, scheme string) {
|
||||||
}
|
}
|
||||||
// Fast import the chain as a non-archive node to test
|
// Fast import the chain as a non-archive node to test
|
||||||
fastDb := rawdb.NewMemoryDatabase()
|
fastDb := rawdb.NewMemoryDatabase()
|
||||||
fast, _ := NewBlockChain(fastDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
fast, _ := NewBlockChain(fastDb, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme))
|
||||||
defer fast.Stop()
|
defer fast.Stop()
|
||||||
|
|
||||||
if n, err := fast.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), 0); err != nil {
|
if n, err := fast.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), 0); err != nil {
|
||||||
|
|
@ -744,7 +745,7 @@ func testFastVsFullChains(t *testing.T, scheme string) {
|
||||||
}
|
}
|
||||||
defer ancientDb.Close()
|
defer ancientDb.Close()
|
||||||
|
|
||||||
ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
ancient, _ := NewBlockChain(ancientDb, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme))
|
||||||
defer ancient.Stop()
|
defer ancient.Stop()
|
||||||
|
|
||||||
if n, err := ancient.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), uint64(len(blocks)/2)); err != nil {
|
if n, err := ancient.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), uint64(len(blocks)/2)); err != nil {
|
||||||
|
|
@ -851,11 +852,8 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) {
|
||||||
archiveDb := makeDb()
|
archiveDb := makeDb()
|
||||||
defer archiveDb.Close()
|
defer archiveDb.Close()
|
||||||
|
|
||||||
archiveCaching := *defaultCacheConfig
|
options := DefaultConfig().WithArchive(true).WithStateScheme(scheme)
|
||||||
archiveCaching.TrieDirtyDisabled = true
|
archive, _ := NewBlockChain(archiveDb, gspec, ethash.NewFaker(), options)
|
||||||
archiveCaching.StateScheme = scheme
|
|
||||||
|
|
||||||
archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
|
||||||
if n, err := archive.InsertChain(blocks); err != nil {
|
if n, err := archive.InsertChain(blocks); err != nil {
|
||||||
t.Fatalf("failed to process block %d: %v", n, err)
|
t.Fatalf("failed to process block %d: %v", n, err)
|
||||||
}
|
}
|
||||||
|
|
@ -868,7 +866,7 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) {
|
||||||
// Import the chain as a non-archive node and ensure all pointers are updated
|
// Import the chain as a non-archive node and ensure all pointers are updated
|
||||||
fastDb := makeDb()
|
fastDb := makeDb()
|
||||||
defer fastDb.Close()
|
defer fastDb.Close()
|
||||||
fast, _ := NewBlockChain(fastDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
fast, _ := NewBlockChain(fastDb, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme))
|
||||||
defer fast.Stop()
|
defer fast.Stop()
|
||||||
|
|
||||||
if n, err := fast.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), 0); err != nil {
|
if n, err := fast.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), 0); err != nil {
|
||||||
|
|
@ -881,7 +879,7 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) {
|
||||||
// Import the chain as a ancient-first node and ensure all pointers are updated
|
// Import the chain as a ancient-first node and ensure all pointers are updated
|
||||||
ancientDb := makeDb()
|
ancientDb := makeDb()
|
||||||
defer ancientDb.Close()
|
defer ancientDb.Close()
|
||||||
ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
ancient, _ := NewBlockChain(ancientDb, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme))
|
||||||
defer ancient.Stop()
|
defer ancient.Stop()
|
||||||
|
|
||||||
if n, err := ancient.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), uint64(3*len(blocks)/4)); err != nil {
|
if n, err := ancient.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), uint64(3*len(blocks)/4)); err != nil {
|
||||||
|
|
@ -902,7 +900,7 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) {
|
||||||
for i, block := range blocks {
|
for i, block := range blocks {
|
||||||
headers[i] = block.Header()
|
headers[i] = block.Header()
|
||||||
}
|
}
|
||||||
light, _ := NewBlockChain(lightDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
light, _ := NewBlockChain(lightDb, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme))
|
||||||
if n, err := light.InsertHeaderChain(headers); err != nil {
|
if n, err := light.InsertHeaderChain(headers); err != nil {
|
||||||
t.Fatalf("failed to insert header %d: %v", n, err)
|
t.Fatalf("failed to insert header %d: %v", n, err)
|
||||||
}
|
}
|
||||||
|
|
@ -975,7 +973,7 @@ func testChainTxReorgs(t *testing.T, scheme string) {
|
||||||
})
|
})
|
||||||
// Import the chain. This runs all block validation rules.
|
// Import the chain. This runs all block validation rules.
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
blockchain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
blockchain, _ := NewBlockChain(db, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme))
|
||||||
if i, err := blockchain.InsertChain(chain); err != nil {
|
if i, err := blockchain.InsertChain(chain); err != nil {
|
||||||
t.Fatalf("failed to insert original chain[%d]: %v", i, err)
|
t.Fatalf("failed to insert original chain[%d]: %v", i, err)
|
||||||
}
|
}
|
||||||
|
|
@ -1049,7 +1047,7 @@ func testLogReorgs(t *testing.T, scheme string) {
|
||||||
signer = types.LatestSigner(gspec.Config)
|
signer = types.LatestSigner(gspec.Config)
|
||||||
)
|
)
|
||||||
|
|
||||||
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme))
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
|
|
||||||
rmLogsCh := make(chan RemovedLogsEvent)
|
rmLogsCh := make(chan RemovedLogsEvent)
|
||||||
|
|
@ -1105,7 +1103,7 @@ func testLogRebirth(t *testing.T, scheme string) {
|
||||||
gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
|
gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
|
||||||
signer = types.LatestSigner(gspec.Config)
|
signer = types.LatestSigner(gspec.Config)
|
||||||
engine = ethash.NewFaker()
|
engine = ethash.NewFaker()
|
||||||
blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil)
|
blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, DefaultConfig().WithStateScheme(scheme))
|
||||||
)
|
)
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
|
|
||||||
|
|
@ -1186,7 +1184,7 @@ func testSideLogRebirth(t *testing.T, scheme string) {
|
||||||
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
||||||
gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
|
gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
|
||||||
signer = types.LatestSigner(gspec.Config)
|
signer = types.LatestSigner(gspec.Config)
|
||||||
blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme))
|
||||||
)
|
)
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
|
|
||||||
|
|
@ -1385,7 +1383,7 @@ func testEIP155Transition(t *testing.T, scheme string) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme))
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
|
|
||||||
if _, err := blockchain.InsertChain(blocks); err != nil {
|
if _, err := blockchain.InsertChain(blocks); err != nil {
|
||||||
|
|
@ -1478,7 +1476,7 @@ func testEIP161AccountRemoval(t *testing.T, scheme string) {
|
||||||
block.AddTx(tx)
|
block.AddTx(tx)
|
||||||
})
|
})
|
||||||
// account must exist pre eip 161
|
// account must exist pre eip 161
|
||||||
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme))
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
|
|
||||||
if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil {
|
if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil {
|
||||||
|
|
@ -1536,7 +1534,7 @@ func testBlockchainHeaderchainReorgConsistency(t *testing.T, scheme string) {
|
||||||
}
|
}
|
||||||
// Import the canonical and fork chain side by side, verifying the current block
|
// Import the canonical and fork chain side by side, verifying the current block
|
||||||
// and current header consistency
|
// and current header consistency
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), genesis, engine, DefaultConfig().WithStateScheme(scheme))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1580,7 +1578,7 @@ func TestTrieForkGC(t *testing.T) {
|
||||||
forks[i] = fork[0]
|
forks[i] = fork[0]
|
||||||
}
|
}
|
||||||
// Import the canonical and fork chain side by side, forcing the trie cache to cache both
|
// Import the canonical and fork chain side by side, forcing the trie cache to cache both
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), genesis, engine, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1626,7 +1624,7 @@ func testLargeReorgTrieGC(t *testing.T, scheme string) {
|
||||||
db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(db, genesis, engine, DefaultConfig().WithStateScheme(scheme))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1694,7 +1692,7 @@ func testBlockchainRecovery(t *testing.T, scheme string) {
|
||||||
t.Fatalf("failed to create temp freezer db: %v", err)
|
t.Fatalf("failed to create temp freezer db: %v", err)
|
||||||
}
|
}
|
||||||
defer ancientDb.Close()
|
defer ancientDb.Close()
|
||||||
ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
ancient, _ := NewBlockChain(ancientDb, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme))
|
||||||
|
|
||||||
if n, err := ancient.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), uint64(3*len(blocks)/4)); err != nil {
|
if n, err := ancient.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), uint64(3*len(blocks)/4)); err != nil {
|
||||||
t.Fatalf("failed to insert receipt %d: %v", n, err)
|
t.Fatalf("failed to insert receipt %d: %v", n, err)
|
||||||
|
|
@ -1707,7 +1705,7 @@ func testBlockchainRecovery(t *testing.T, scheme string) {
|
||||||
rawdb.WriteHeadFastBlockHash(ancientDb, midBlock.Hash())
|
rawdb.WriteHeadFastBlockHash(ancientDb, midBlock.Hash())
|
||||||
|
|
||||||
// Reopen broken blockchain again
|
// Reopen broken blockchain again
|
||||||
ancient, _ = NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
ancient, _ = NewBlockChain(ancientDb, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme))
|
||||||
defer ancient.Stop()
|
defer ancient.Stop()
|
||||||
if num := ancient.CurrentBlock().Number.Uint64(); num != 0 {
|
if num := ancient.CurrentBlock().Number.Uint64(); num != 0 {
|
||||||
t.Errorf("head block mismatch: have #%v, want #%v", num, 0)
|
t.Errorf("head block mismatch: have #%v, want #%v", num, 0)
|
||||||
|
|
@ -1750,7 +1748,7 @@ func testLowDiffLongChain(t *testing.T, scheme string) {
|
||||||
diskdb, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
diskdb, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
||||||
defer diskdb.Close()
|
defer diskdb.Close()
|
||||||
|
|
||||||
chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(diskdb, genesis, engine, DefaultConfig().WithStateScheme(scheme))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1811,7 +1809,7 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
||||||
mergeBlock = gomath.MaxInt32
|
mergeBlock = gomath.MaxInt32
|
||||||
)
|
)
|
||||||
// Generate and import the canonical chain
|
// Generate and import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1965,7 +1963,7 @@ func testInsertKnownChainData(t *testing.T, typ string, scheme string) {
|
||||||
}
|
}
|
||||||
defer chaindb.Close()
|
defer chaindb.Close()
|
||||||
|
|
||||||
chain, err := NewBlockChain(chaindb, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(chaindb, genesis, engine, DefaultConfig().WithStateScheme(scheme))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -2128,7 +2126,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
|
||||||
}
|
}
|
||||||
defer chaindb.Close()
|
defer chaindb.Close()
|
||||||
|
|
||||||
chain, err := NewBlockChain(chaindb, nil, genesis, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(chaindb, genesis, engine, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -2234,7 +2232,7 @@ func getLongAndShortChains(scheme string) (*BlockChain, []*types.Block, []*types
|
||||||
genDb, longChain, _ := GenerateChainWithGenesis(genesis, engine, 80, func(i int, b *BlockGen) {
|
genDb, longChain, _ := GenerateChainWithGenesis(genesis, engine, 80, func(i int, b *BlockGen) {
|
||||||
b.SetCoinbase(common.Address{1})
|
b.SetCoinbase(common.Address{1})
|
||||||
})
|
})
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), genesis, engine, DefaultConfig().WithStateScheme(scheme))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, fmt.Errorf("failed to create tester chain: %v", err)
|
return nil, nil, nil, nil, fmt.Errorf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -2410,7 +2408,7 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
// Import the shared chain and the original canonical one
|
// Import the shared chain and the original canonical one
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("failed to create tester chain: %v", err)
|
b.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -2502,7 +2500,7 @@ func testSideImportPrunedBlocks(t *testing.T, scheme string) {
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(db, genesis, engine, DefaultConfig().WithStateScheme(scheme))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -2601,7 +2599,8 @@ func testDeleteCreateRevert(t *testing.T, scheme string) {
|
||||||
b.AddTx(tx)
|
b.AddTx(tx)
|
||||||
})
|
})
|
||||||
// Import the canonical chain
|
// Import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil)
|
options := DefaultConfig().WithStateScheme(scheme)
|
||||||
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -2714,9 +2713,11 @@ func testDeleteRecreateSlots(t *testing.T, scheme string) {
|
||||||
b.AddTx(tx)
|
b.AddTx(tx)
|
||||||
})
|
})
|
||||||
// Import the canonical chain
|
// Import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
|
options := DefaultConfig().WithStateScheme(scheme)
|
||||||
|
options.VmConfig = vm.Config{
|
||||||
Tracer: logger.NewJSONLogger(nil, os.Stdout),
|
Tracer: logger.NewJSONLogger(nil, os.Stdout),
|
||||||
}, nil)
|
}
|
||||||
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -2796,9 +2797,11 @@ func testDeleteRecreateAccount(t *testing.T, scheme string) {
|
||||||
b.AddTx(tx)
|
b.AddTx(tx)
|
||||||
})
|
})
|
||||||
// Import the canonical chain
|
// Import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
|
options := DefaultConfig().WithStateScheme(scheme)
|
||||||
|
options.VmConfig = vm.Config{
|
||||||
Tracer: logger.NewJSONLogger(nil, os.Stdout),
|
Tracer: logger.NewJSONLogger(nil, os.Stdout),
|
||||||
}, nil)
|
}
|
||||||
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -2971,10 +2974,12 @@ func testDeleteRecreateSlotsAcrossManyBlocks(t *testing.T, scheme string) {
|
||||||
current = exp
|
current = exp
|
||||||
})
|
})
|
||||||
// Import the canonical chain
|
// Import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
|
options := DefaultConfig().WithStateScheme(scheme)
|
||||||
|
options.VmConfig = vm.Config{
|
||||||
//Debug: true,
|
//Debug: true,
|
||||||
//Tracer: vm.NewJSONLogger(nil, os.Stdout),
|
//Tracer: vm.NewJSONLogger(nil, os.Stdout),
|
||||||
}, nil)
|
}
|
||||||
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -3109,10 +3114,12 @@ func testInitThenFailCreateContract(t *testing.T, scheme string) {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Import the canonical chain
|
// Import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
|
options := DefaultConfig().WithStateScheme(scheme)
|
||||||
|
options.VmConfig = vm.Config{
|
||||||
//Debug: true,
|
//Debug: true,
|
||||||
//Tracer: vm.NewJSONLogger(nil, os.Stdout),
|
//Tracer: vm.NewJSONLogger(nil, os.Stdout),
|
||||||
}, nil)
|
}
|
||||||
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -3199,7 +3206,8 @@ func testEIP2718Transition(t *testing.T, scheme string) {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Import the canonical chain
|
// Import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil)
|
options := DefaultConfig().WithStateScheme(scheme)
|
||||||
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -3293,7 +3301,8 @@ func testEIP1559Transition(t *testing.T, scheme string) {
|
||||||
|
|
||||||
b.AddTx(tx)
|
b.AddTx(tx)
|
||||||
})
|
})
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil)
|
options := DefaultConfig().WithStateScheme(scheme)
|
||||||
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -3406,7 +3415,8 @@ func testSetCanonical(t *testing.T, scheme string) {
|
||||||
diskdb, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
diskdb, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
||||||
defer diskdb.Close()
|
defer diskdb.Close()
|
||||||
|
|
||||||
chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil)
|
options := DefaultConfig().WithStateScheme(scheme)
|
||||||
|
chain, err := NewBlockChain(diskdb, gspec, engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -3515,7 +3525,8 @@ func testCanonicalHashMarker(t *testing.T, scheme string) {
|
||||||
_, forkB, _ := GenerateChainWithGenesis(gspec, engine, c.forkB, func(i int, gen *BlockGen) {})
|
_, forkB, _ := GenerateChainWithGenesis(gspec, engine, c.forkB, func(i int, gen *BlockGen) {})
|
||||||
|
|
||||||
// Initialize test chain
|
// Initialize test chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil)
|
options := DefaultConfig().WithStateScheme(scheme)
|
||||||
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -3649,10 +3660,7 @@ func testCreateThenDelete(t *testing.T, config *params.ChainConfig) {
|
||||||
nonce++
|
nonce++
|
||||||
})
|
})
|
||||||
// Import the canonical chain
|
// Import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, nil)
|
||||||
//Debug: true,
|
|
||||||
//Tracer: logger.NewJSONLogger(nil, os.Stdout),
|
|
||||||
}, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -3764,7 +3772,7 @@ func TestDeleteThenCreate(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// Import the canonical chain
|
// Import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -3849,7 +3857,9 @@ func TestTransientStorageReset(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Initialize the blockchain with 1153 enabled.
|
// Initialize the blockchain with 1153 enabled.
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vmConfig, nil)
|
options := DefaultConfig()
|
||||||
|
options.VmConfig = vmConfig
|
||||||
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -3943,7 +3953,11 @@ func TestEIP3651(t *testing.T) {
|
||||||
|
|
||||||
b.AddTx(tx)
|
b.AddTx(tx)
|
||||||
})
|
})
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{Tracer: logger.NewMarkdownLogger(&logger.Config{}, os.Stderr).Hooks()}, nil)
|
options := DefaultConfig()
|
||||||
|
options.VmConfig = vm.Config{
|
||||||
|
Tracer: logger.NewMarkdownLogger(&logger.Config{}, os.Stderr).Hooks(),
|
||||||
|
}
|
||||||
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -4052,7 +4066,7 @@ func TestPragueRequests(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert block to check validation.
|
// Insert block to check validation.
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -4124,7 +4138,7 @@ func TestEIP7702(t *testing.T) {
|
||||||
tx := types.MustSignNewTx(key1, signer, txdata)
|
tx := types.MustSignNewTx(key1, signer, txdata)
|
||||||
b.AddTx(tx)
|
b.AddTx(tx)
|
||||||
})
|
})
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -4202,7 +4216,8 @@ func testChainReorgSnapSync(t *testing.T, ancientLimit uint64) {
|
||||||
db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
chain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(rawdb.PathScheme), gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil)
|
options := DefaultConfig().WithStateScheme(rawdb.PathScheme)
|
||||||
|
chain, _ := NewBlockChain(db, gspec, beacon.New(ethash.NewFaker()), options)
|
||||||
defer chain.Stop()
|
defer chain.Stop()
|
||||||
|
|
||||||
if n, err := chain.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), ancientLimit); err != nil {
|
if n, err := chain.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), ancientLimit); err != nil {
|
||||||
|
|
@ -4312,12 +4327,14 @@ func testInsertChainWithCutoff(t *testing.T, cutoff uint64, ancientLimit uint64,
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Enable pruning in cache config.
|
// Enable pruning in cache config.
|
||||||
config := DefaultCacheConfigWithScheme(rawdb.PathScheme)
|
config := DefaultConfig().WithStateScheme(rawdb.PathScheme)
|
||||||
config.ChainHistoryMode = history.KeepPostMerge
|
config.ChainHistoryMode = history.KeepPostMerge
|
||||||
|
|
||||||
db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
chain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(rawdb.PathScheme), genesis, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil)
|
|
||||||
|
options := DefaultConfig().WithStateScheme(rawdb.PathScheme)
|
||||||
|
chain, _ := NewBlockChain(db, genesis, beacon.New(ethash.NewFaker()), options)
|
||||||
defer chain.Stop()
|
defer chain.Stop()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -579,7 +579,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
|
||||||
|
|
||||||
func GenerateVerkleChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (common.Hash, ethdb.Database, []*types.Block, []types.Receipts, []*verkle.VerkleProof, []verkle.StateDiff) {
|
func GenerateVerkleChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (common.Hash, ethdb.Database, []*types.Block, []types.Receipts, []*verkle.VerkleProof, []verkle.StateDiff) {
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme)
|
cacheConfig := DefaultConfig().WithStateScheme(rawdb.PathScheme)
|
||||||
cacheConfig.SnapshotLimit = 0
|
cacheConfig.SnapshotLimit = 0
|
||||||
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true))
|
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true))
|
||||||
defer triedb.Close()
|
defer triedb.Close()
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/triedb"
|
"github.com/ethereum/go-ethereum/triedb"
|
||||||
|
|
@ -119,7 +118,7 @@ func TestGeneratePOSChain(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Import the chain. This runs all block validation rules.
|
// Import the chain. This runs all block validation rules.
|
||||||
blockchain, _ := NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil)
|
blockchain, _ := NewBlockChain(db, gspec, engine, nil)
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
|
|
||||||
if i, err := blockchain.InsertChain(genchain); err != nil {
|
if i, err := blockchain.InsertChain(genchain); err != nil {
|
||||||
|
|
@ -234,7 +233,7 @@ func ExampleGenerateChain() {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Import the chain. This runs all block validation rules.
|
// Import the chain. This runs all block validation rules.
|
||||||
blockchain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(rawdb.HashScheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
blockchain, _ := NewBlockChain(db, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(rawdb.HashScheme))
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
|
|
||||||
if i, err := blockchain.InsertChain(chain); err != nil {
|
if i, err := blockchain.InsertChain(chain); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -50,7 +49,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||||
Config: &proConf,
|
Config: &proConf,
|
||||||
}
|
}
|
||||||
proBc, _ := NewBlockChain(proDb, nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
proBc, _ := NewBlockChain(proDb, progspec, ethash.NewFaker(), nil)
|
||||||
defer proBc.Stop()
|
defer proBc.Stop()
|
||||||
|
|
||||||
conDb := rawdb.NewMemoryDatabase()
|
conDb := rawdb.NewMemoryDatabase()
|
||||||
|
|
@ -62,7 +61,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||||
Config: &conConf,
|
Config: &conConf,
|
||||||
}
|
}
|
||||||
conBc, _ := NewBlockChain(conDb, nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
conBc, _ := NewBlockChain(conDb, congspec, ethash.NewFaker(), nil)
|
||||||
defer conBc.Stop()
|
defer conBc.Stop()
|
||||||
|
|
||||||
if _, err := proBc.InsertChain(prefix); err != nil {
|
if _, err := proBc.InsertChain(prefix); err != nil {
|
||||||
|
|
@ -74,7 +73,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
// Try to expand both pro-fork and non-fork chains iteratively with other camp's blocks
|
// Try to expand both pro-fork and non-fork chains iteratively with other camp's blocks
|
||||||
for i := int64(0); i < params.DAOForkExtraRange.Int64(); i++ {
|
for i := int64(0); i < params.DAOForkExtraRange.Int64(); i++ {
|
||||||
// Create a pro-fork block, and try to feed into the no-fork chain
|
// Create a pro-fork block, and try to feed into the no-fork chain
|
||||||
bc, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
bc, _ := NewBlockChain(rawdb.NewMemoryDatabase(), congspec, ethash.NewFaker(), nil)
|
||||||
|
|
||||||
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().Number.Uint64()))
|
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().Number.Uint64()))
|
||||||
for j := 0; j < len(blocks)/2; j++ {
|
for j := 0; j < len(blocks)/2; j++ {
|
||||||
|
|
@ -97,7 +96,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
t.Fatalf("contra-fork chain didn't accepted no-fork block: %v", err)
|
t.Fatalf("contra-fork chain didn't accepted no-fork block: %v", err)
|
||||||
}
|
}
|
||||||
// Create a no-fork block, and try to feed into the pro-fork chain
|
// Create a no-fork block, and try to feed into the pro-fork chain
|
||||||
bc, _ = NewBlockChain(rawdb.NewMemoryDatabase(), nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
bc, _ = NewBlockChain(rawdb.NewMemoryDatabase(), progspec, ethash.NewFaker(), nil)
|
||||||
|
|
||||||
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64()))
|
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64()))
|
||||||
for j := 0; j < len(blocks)/2; j++ {
|
for j := 0; j < len(blocks)/2; j++ {
|
||||||
|
|
@ -121,7 +120,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Verify that contra-forkers accept pro-fork extra-datas after forking finishes
|
// Verify that contra-forkers accept pro-fork extra-datas after forking finishes
|
||||||
bc, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
bc, _ := NewBlockChain(rawdb.NewMemoryDatabase(), congspec, ethash.NewFaker(), nil)
|
||||||
defer bc.Stop()
|
defer bc.Stop()
|
||||||
|
|
||||||
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().Number.Uint64()))
|
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().Number.Uint64()))
|
||||||
|
|
@ -139,7 +138,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err)
|
t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err)
|
||||||
}
|
}
|
||||||
// Verify that pro-forkers accept contra-fork extra-datas after forking finishes
|
// Verify that pro-forkers accept contra-fork extra-datas after forking finishes
|
||||||
bc, _ = NewBlockChain(rawdb.NewMemoryDatabase(), nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
bc, _ = NewBlockChain(rawdb.NewMemoryDatabase(), progspec, ethash.NewFaker(), nil)
|
||||||
defer bc.Stop()
|
defer bc.Stop()
|
||||||
|
|
||||||
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64()))
|
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64()))
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/triedb"
|
"github.com/ethereum/go-ethereum/triedb"
|
||||||
|
|
@ -149,7 +148,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
|
||||||
tdb := triedb.NewDatabase(db, newDbConfig(scheme))
|
tdb := triedb.NewDatabase(db, newDbConfig(scheme))
|
||||||
oldcustomg.Commit(db, tdb)
|
oldcustomg.Commit(db, tdb)
|
||||||
|
|
||||||
bc, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), &oldcustomg, nil, ethash.NewFullFaker(), vm.Config{}, nil)
|
bc, _ := NewBlockChain(db, &oldcustomg, ethash.NewFullFaker(), DefaultConfig().WithStateScheme(scheme))
|
||||||
defer bc.Stop()
|
defer bc.Stop()
|
||||||
|
|
||||||
_, blocks, _ := GenerateChainWithGenesis(&oldcustomg, ethash.NewFaker(), 4, nil)
|
_, blocks, _ := GenerateChainWithGenesis(&oldcustomg, ethash.NewFaker(), 4, nil)
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,11 @@ func (t *table) Delete(key []byte) error {
|
||||||
// DeleteRange deletes all of the keys (and values) in the range [start,end)
|
// DeleteRange deletes all of the keys (and values) in the range [start,end)
|
||||||
// (inclusive on start, exclusive on end).
|
// (inclusive on start, exclusive on end).
|
||||||
func (t *table) DeleteRange(start, end []byte) error {
|
func (t *table) DeleteRange(start, end []byte) error {
|
||||||
|
// The nilness will be lost by adding the prefix, explicitly converting it
|
||||||
|
// to a special flag representing the end of key range.
|
||||||
|
if end == nil {
|
||||||
|
end = ethdb.MaximumKey
|
||||||
|
}
|
||||||
return t.db.DeleteRange(append([]byte(t.prefix), start...), append([]byte(t.prefix), end...))
|
return t.db.DeleteRange(append([]byte(t.prefix), start...), append([]byte(t.prefix), end...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -217,6 +222,16 @@ func (b *tableBatch) Delete(key []byte) error {
|
||||||
return b.batch.Delete(append([]byte(b.prefix), key...))
|
return b.batch.Delete(append([]byte(b.prefix), key...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteRange removes all keys in the range [start, end) from the batch for later committing.
|
||||||
|
func (b *tableBatch) DeleteRange(start, end []byte) error {
|
||||||
|
// The nilness will be lost by adding the prefix, explicitly converting it
|
||||||
|
// to a special flag representing the end of key range.
|
||||||
|
if end == nil {
|
||||||
|
end = ethdb.MaximumKey
|
||||||
|
}
|
||||||
|
return b.batch.DeleteRange(append([]byte(b.prefix), start...), append([]byte(b.prefix), end...))
|
||||||
|
}
|
||||||
|
|
||||||
// ValueSize retrieves the amount of data queued up for writing.
|
// ValueSize retrieves the amount of data queued up for writing.
|
||||||
func (b *tableBatch) ValueSize() int {
|
func (b *tableBatch) ValueSize() int {
|
||||||
return b.batch.ValueSize()
|
return b.batch.ValueSize()
|
||||||
|
|
|
||||||
|
|
@ -125,4 +125,28 @@ func testTableDatabase(t *testing.T, prefix string) {
|
||||||
// Test iterators with prefix and start point
|
// Test iterators with prefix and start point
|
||||||
check(db.NewIterator([]byte{0xee}, nil), 0, 0)
|
check(db.NewIterator([]byte{0xee}, nil), 0, 0)
|
||||||
check(db.NewIterator(nil, []byte{0x00}), 6, 0)
|
check(db.NewIterator(nil, []byte{0x00}), 6, 0)
|
||||||
|
|
||||||
|
// Test range deletion
|
||||||
|
db.DeleteRange(nil, nil)
|
||||||
|
for _, entry := range entries {
|
||||||
|
_, err := db.Get(entry.key)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("Unexpected item after deletion")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Test range deletion by batch
|
||||||
|
batch = db.NewBatch()
|
||||||
|
for _, entry := range entries {
|
||||||
|
batch.Put(entry.key, entry.value)
|
||||||
|
}
|
||||||
|
batch.Write()
|
||||||
|
batch.Reset()
|
||||||
|
batch.DeleteRange(nil, nil)
|
||||||
|
batch.Write()
|
||||||
|
for _, entry := range entries {
|
||||||
|
_, err := db.Get(entry.key)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("Unexpected item after deletion")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -209,13 +209,16 @@ func (db *CachingDB) Reader(stateRoot common.Hash) (Reader, error) {
|
||||||
return newReader(newCachingCodeReader(db.disk, db.codeCache, db.codeSizeCache), combined), nil
|
return newReader(newCachingCodeReader(db.disk, db.codeCache, db.codeSizeCache), combined), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReaderWithCache creates a state reader with internal local cache.
|
// ReadersWithCacheStats creates a pair of state readers sharing the same internal cache and
|
||||||
func (db *CachingDB) ReaderWithCache(stateRoot common.Hash) (Reader, error) {
|
// same backing Reader, but exposing separate statistics.
|
||||||
|
// and statistics.
|
||||||
|
func (db *CachingDB) ReadersWithCacheStats(stateRoot common.Hash) (ReaderWithStats, ReaderWithStats, error) {
|
||||||
reader, err := db.Reader(stateRoot)
|
reader, err := db.Reader(stateRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
return newReaderWithCache(reader), nil
|
shared := newReaderWithCache(reader)
|
||||||
|
return newReaderWithCacheStats(shared), newReaderWithCacheStats(shared), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenTrie opens the main account trie at a specific root hash.
|
// OpenTrie opens the main account trie at a specific root hash.
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ package state
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/lru"
|
"github.com/ethereum/go-ethereum/common/lru"
|
||||||
|
|
@ -82,6 +83,20 @@ type Reader interface {
|
||||||
StateReader
|
StateReader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReaderStats wraps the statistics of reader.
|
||||||
|
type ReaderStats struct {
|
||||||
|
AccountHit int64
|
||||||
|
AccountMiss int64
|
||||||
|
StorageHit int64
|
||||||
|
StorageMiss int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReaderWithStats wraps the additional method to retrieve the reader statistics from.
|
||||||
|
type ReaderWithStats interface {
|
||||||
|
Reader
|
||||||
|
GetStats() ReaderStats
|
||||||
|
}
|
||||||
|
|
||||||
// cachingCodeReader implements ContractCodeReader, accessing contract code either in
|
// cachingCodeReader implements ContractCodeReader, accessing contract code either in
|
||||||
// local key-value store or the shared code cache.
|
// local key-value store or the shared code cache.
|
||||||
//
|
//
|
||||||
|
|
@ -414,35 +429,43 @@ func newReaderWithCache(reader Reader) *readerWithCache {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account implements StateReader, retrieving the account specified by the address.
|
// account retrieves the account specified by the address along with a flag
|
||||||
// The returned account might be nil if it's not existent.
|
// indicating whether it's found in the cache or not. The returned account
|
||||||
|
// might be nil if it's not existent.
|
||||||
//
|
//
|
||||||
// An error will be returned if the state is corrupted in the underlying reader.
|
// An error will be returned if the state is corrupted in the underlying reader.
|
||||||
func (r *readerWithCache) Account(addr common.Address) (*types.StateAccount, error) {
|
func (r *readerWithCache) account(addr common.Address) (*types.StateAccount, bool, error) {
|
||||||
// Try to resolve the requested account in the local cache
|
// Try to resolve the requested account in the local cache
|
||||||
r.accountLock.RLock()
|
r.accountLock.RLock()
|
||||||
acct, ok := r.accounts[addr]
|
acct, ok := r.accounts[addr]
|
||||||
r.accountLock.RUnlock()
|
r.accountLock.RUnlock()
|
||||||
if ok {
|
if ok {
|
||||||
return acct, nil
|
return acct, true, nil
|
||||||
}
|
}
|
||||||
// Try to resolve the requested account from the underlying reader
|
// Try to resolve the requested account from the underlying reader
|
||||||
acct, err := r.Reader.Account(addr)
|
acct, err := r.Reader.Account(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
r.accountLock.Lock()
|
r.accountLock.Lock()
|
||||||
r.accounts[addr] = acct
|
r.accounts[addr] = acct
|
||||||
r.accountLock.Unlock()
|
r.accountLock.Unlock()
|
||||||
return acct, nil
|
return acct, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Storage implements StateReader, retrieving the storage slot specified by the
|
// Account implements StateReader, retrieving the account specified by the address.
|
||||||
// address and slot key. The returned storage slot might be empty if it's not
|
// The returned account might be nil if it's not existent.
|
||||||
// existent.
|
|
||||||
//
|
//
|
||||||
// An error will be returned if the state is corrupted in the underlying reader.
|
// An error will be returned if the state is corrupted in the underlying reader.
|
||||||
func (r *readerWithCache) Storage(addr common.Address, slot common.Hash) (common.Hash, error) {
|
func (r *readerWithCache) Account(addr common.Address) (*types.StateAccount, error) {
|
||||||
|
account, _, err := r.account(addr)
|
||||||
|
return account, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// storage retrieves the storage slot specified by the address and slot key, along
|
||||||
|
// with a flag indicating whether it's found in the cache or not. The returned
|
||||||
|
// storage slot might be empty if it's not existent.
|
||||||
|
func (r *readerWithCache) storage(addr common.Address, slot common.Hash) (common.Hash, bool, error) {
|
||||||
var (
|
var (
|
||||||
value common.Hash
|
value common.Hash
|
||||||
ok bool
|
ok bool
|
||||||
|
|
@ -456,12 +479,12 @@ func (r *readerWithCache) Storage(addr common.Address, slot common.Hash) (common
|
||||||
}
|
}
|
||||||
bucket.lock.RUnlock()
|
bucket.lock.RUnlock()
|
||||||
if ok {
|
if ok {
|
||||||
return value, nil
|
return value, true, nil
|
||||||
}
|
}
|
||||||
// Try to resolve the requested storage slot from the underlying reader
|
// Try to resolve the requested storage slot from the underlying reader
|
||||||
value, err := r.Reader.Storage(addr, slot)
|
value, err := r.Reader.Storage(addr, slot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Hash{}, err
|
return common.Hash{}, false, err
|
||||||
}
|
}
|
||||||
bucket.lock.Lock()
|
bucket.lock.Lock()
|
||||||
slots, ok = bucket.storages[addr]
|
slots, ok = bucket.storages[addr]
|
||||||
|
|
@ -472,5 +495,75 @@ func (r *readerWithCache) Storage(addr common.Address, slot common.Hash) (common
|
||||||
slots[slot] = value
|
slots[slot] = value
|
||||||
bucket.lock.Unlock()
|
bucket.lock.Unlock()
|
||||||
|
|
||||||
|
return value, false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Storage implements StateReader, retrieving the storage slot specified by the
|
||||||
|
// address and slot key. The returned storage slot might be empty if it's not
|
||||||
|
// existent.
|
||||||
|
//
|
||||||
|
// An error will be returned if the state is corrupted in the underlying reader.
|
||||||
|
func (r *readerWithCache) Storage(addr common.Address, slot common.Hash) (common.Hash, error) {
|
||||||
|
value, _, err := r.storage(addr, slot)
|
||||||
|
return value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type readerWithCacheStats struct {
|
||||||
|
*readerWithCache
|
||||||
|
accountHit atomic.Int64
|
||||||
|
accountMiss atomic.Int64
|
||||||
|
storageHit atomic.Int64
|
||||||
|
storageMiss atomic.Int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// newReaderWithCacheStats constructs the reader with additional statistics tracked.
|
||||||
|
func newReaderWithCacheStats(reader *readerWithCache) *readerWithCacheStats {
|
||||||
|
return &readerWithCacheStats{
|
||||||
|
readerWithCache: reader,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account implements StateReader, retrieving the account specified by the address.
|
||||||
|
// The returned account might be nil if it's not existent.
|
||||||
|
//
|
||||||
|
// An error will be returned if the state is corrupted in the underlying reader.
|
||||||
|
func (r *readerWithCacheStats) Account(addr common.Address) (*types.StateAccount, error) {
|
||||||
|
account, incache, err := r.readerWithCache.account(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if incache {
|
||||||
|
r.accountHit.Add(1)
|
||||||
|
} else {
|
||||||
|
r.accountMiss.Add(1)
|
||||||
|
}
|
||||||
|
return account, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Storage implements StateReader, retrieving the storage slot specified by the
|
||||||
|
// address and slot key. The returned storage slot might be empty if it's not
|
||||||
|
// existent.
|
||||||
|
//
|
||||||
|
// An error will be returned if the state is corrupted in the underlying reader.
|
||||||
|
func (r *readerWithCacheStats) Storage(addr common.Address, slot common.Hash) (common.Hash, error) {
|
||||||
|
value, incache, err := r.readerWithCache.storage(addr, slot)
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, err
|
||||||
|
}
|
||||||
|
if incache {
|
||||||
|
r.storageHit.Add(1)
|
||||||
|
} else {
|
||||||
|
r.storageMiss.Add(1)
|
||||||
|
}
|
||||||
return value, nil
|
return value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetStats implements ReaderWithStats, returning the statistics of state reader.
|
||||||
|
func (r *readerWithCacheStats) GetStats() ReaderStats {
|
||||||
|
return ReaderStats{
|
||||||
|
AccountHit: r.accountHit.Load(),
|
||||||
|
AccountMiss: r.accountMiss.Load(),
|
||||||
|
StorageHit: r.storageHit.Load(),
|
||||||
|
StorageMiss: r.storageMiss.Load(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
|
||||||
workers errgroup.Group
|
workers errgroup.Group
|
||||||
reader = statedb.Reader()
|
reader = statedb.Reader()
|
||||||
)
|
)
|
||||||
workers.SetLimit(runtime.NumCPU() / 2)
|
workers.SetLimit(4 * runtime.NumCPU() / 5) // Aggressively run the prefetching
|
||||||
|
|
||||||
// Iterate over and process the individual transactions
|
// Iterate over and process the individual transactions
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
|
@ -125,7 +124,7 @@ func TestStateProcessorErrors(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
blockchain, _ = NewBlockChain(db, nil, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil)
|
blockchain, _ = NewBlockChain(db, gspec, beacon.New(ethash.NewFaker()), nil)
|
||||||
tooBigInitCode = [params.MaxInitCodeSize + 1]byte{}
|
tooBigInitCode = [params.MaxInitCodeSize + 1]byte{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -293,7 +292,7 @@ func TestStateProcessorErrors(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
blockchain, _ = NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
blockchain, _ = NewBlockChain(db, gspec, ethash.NewFaker(), nil)
|
||||||
)
|
)
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
for i, tt := range []struct {
|
for i, tt := range []struct {
|
||||||
|
|
@ -332,7 +331,7 @@ func TestStateProcessorErrors(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
blockchain, _ = NewBlockChain(db, nil, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil)
|
blockchain, _ = NewBlockChain(db, gspec, beacon.New(ethash.NewFaker()), nil)
|
||||||
)
|
)
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
for i, tt := range []struct {
|
for i, tt := range []struct {
|
||||||
|
|
|
||||||
|
|
@ -534,10 +534,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
||||||
|
|
||||||
effectiveTip := msg.GasPrice
|
effectiveTip := msg.GasPrice
|
||||||
if rules.IsLondon {
|
if rules.IsLondon {
|
||||||
effectiveTip = new(big.Int).Sub(msg.GasFeeCap, st.evm.Context.BaseFee)
|
effectiveTip = new(big.Int).Sub(msg.GasPrice, st.evm.Context.BaseFee)
|
||||||
if effectiveTip.Cmp(msg.GasTipCap) > 0 {
|
|
||||||
effectiveTip = msg.GasTipCap
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
effectiveTipU256, _ := uint256.FromBig(effectiveTip)
|
effectiveTipU256, _ := uint256.FromBig(effectiveTip)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/txpool"
|
"github.com/ethereum/go-ethereum/core/txpool"
|
||||||
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
|
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -65,7 +64,7 @@ func newTestEnv(t *testing.T, n int, gasTip uint64, journal string) *testEnv {
|
||||||
})
|
})
|
||||||
|
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
chain, _ := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
chain, _ := core.NewBlockChain(db, gspec, ethash.NewFaker(), nil)
|
||||||
|
|
||||||
legacyPool := legacypool.New(legacypool.DefaultConfig, chain)
|
legacyPool := legacypool.New(legacypool.DefaultConfig, chain)
|
||||||
pool, err := txpool.New(gasTip, chain, []txpool.SubPool{legacyPool})
|
pool, err := txpool.New(gasTip, chain, []txpool.SubPool{legacyPool})
|
||||||
|
|
|
||||||
|
|
@ -119,9 +119,9 @@ func TestProcessVerkle(t *testing.T) {
|
||||||
// Verkle trees use the snapshot, which must be enabled before the
|
// Verkle trees use the snapshot, which must be enabled before the
|
||||||
// data is saved into the tree+database.
|
// data is saved into the tree+database.
|
||||||
// genesis := gspec.MustCommit(bcdb, triedb)
|
// genesis := gspec.MustCommit(bcdb, triedb)
|
||||||
cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme)
|
options := DefaultConfig().WithStateScheme(rawdb.PathScheme)
|
||||||
cacheConfig.SnapshotLimit = 0
|
options.SnapshotLimit = 0
|
||||||
blockchain, _ := NewBlockChain(bcdb, cacheConfig, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil)
|
blockchain, _ := NewBlockChain(bcdb, gspec, beacon.New(ethash.NewFaker()), options)
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
|
|
||||||
txCost1 := params.TxGas
|
txCost1 := params.TxGas
|
||||||
|
|
@ -255,7 +255,7 @@ func TestProcessParentBlockHash(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Verkle", func(t *testing.T) {
|
t.Run("Verkle", func(t *testing.T) {
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme)
|
cacheConfig := DefaultConfig().WithStateScheme(rawdb.PathScheme)
|
||||||
cacheConfig.SnapshotLimit = 0
|
cacheConfig.SnapshotLimit = 0
|
||||||
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true))
|
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true))
|
||||||
statedb, _ := state.New(types.EmptyVerkleHash, state.NewDatabase(triedb, nil))
|
statedb, _ := state.New(types.EmptyVerkleHash, state.NewDatabase(triedb, nil))
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ func (c *twistPoint) Set(a *twistPoint) {
|
||||||
c.t.Set(&a.t)
|
c.t.Set(&a.t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsOnCurve returns true iff c is on the curve.
|
// IsOnCurve returns true iff c is on the curve and is in the correct subgroup.
|
||||||
func (c *twistPoint) IsOnCurve() bool {
|
func (c *twistPoint) IsOnCurve() bool {
|
||||||
c.MakeAffine()
|
c.MakeAffine()
|
||||||
if c.IsInfinity() {
|
if c.IsInfinity() {
|
||||||
|
|
@ -57,6 +57,8 @@ func (c *twistPoint) IsOnCurve() bool {
|
||||||
if *y2 != *x3 {
|
if *y2 != *x3 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
// Subgroup check: multiply the point by the group order and
|
||||||
|
// verify that it becomes the point at infinity.
|
||||||
cneg := &twistPoint{}
|
cneg := &twistPoint{}
|
||||||
cneg.Mul(c, Order)
|
cneg.Mul(c, Order)
|
||||||
return cneg.z.IsZero()
|
return cneg.z.IsZero()
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ type G2 struct {
|
||||||
// Unmarshal deserializes `buf` into `g`
|
// Unmarshal deserializes `buf` into `g`
|
||||||
//
|
//
|
||||||
// The input is expected to be in the EVM format:
|
// The input is expected to be in the EVM format:
|
||||||
// 128 bytes: [32-byte x.0][32-byte x.1][32-byte y.0][32-byte y.1]
|
// 128 bytes: [32-byte x.1][32-byte x.0][32-byte y.1][32-byte y.0]
|
||||||
// where each value is a big-endian integer.
|
// where each value is a big-endian integer.
|
||||||
//
|
//
|
||||||
// This method also checks whether the point is on the
|
// This method also checks whether the point is on the
|
||||||
|
|
@ -39,16 +39,16 @@ func (g *G2) Unmarshal(buf []byte) (int, error) {
|
||||||
g.inner.Y.A1.SetZero()
|
g.inner.Y.A1.SetZero()
|
||||||
return 128, nil
|
return 128, nil
|
||||||
}
|
}
|
||||||
if err := g.inner.X.A0.SetBytesCanonical(buf[0:32]); err != nil {
|
if err := g.inner.X.A1.SetBytesCanonical(buf[0:32]); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if err := g.inner.X.A1.SetBytesCanonical(buf[32:64]); err != nil {
|
if err := g.inner.X.A0.SetBytesCanonical(buf[32:64]); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if err := g.inner.Y.A0.SetBytesCanonical(buf[64:96]); err != nil {
|
if err := g.inner.Y.A1.SetBytesCanonical(buf[64:96]); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if err := g.inner.Y.A1.SetBytesCanonical(buf[96:128]); err != nil {
|
if err := g.inner.Y.A0.SetBytesCanonical(buf[96:128]); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,22 +64,22 @@ func (g *G2) Unmarshal(buf []byte) (int, error) {
|
||||||
// Marshal serializes the point into a byte slice.
|
// Marshal serializes the point into a byte slice.
|
||||||
//
|
//
|
||||||
// The output is in EVM format: 128 bytes total.
|
// The output is in EVM format: 128 bytes total.
|
||||||
// [32-byte x.0][32-byte x.1][32-byte y.0][32-byte y.1]
|
// [32-byte x.1][32-byte x.0][32-byte y.1][32-byte y.0]
|
||||||
// where each value is a big-endian integer.
|
// where each value is a big-endian integer.
|
||||||
func (g *G2) Marshal() []byte {
|
func (g *G2) Marshal() []byte {
|
||||||
output := make([]byte, 128)
|
output := make([]byte, 128)
|
||||||
|
|
||||||
xA0Bytes := g.inner.X.A0.Bytes()
|
|
||||||
copy(output[:32], xA0Bytes[:])
|
|
||||||
|
|
||||||
xA1Bytes := g.inner.X.A1.Bytes()
|
xA1Bytes := g.inner.X.A1.Bytes()
|
||||||
copy(output[32:64], xA1Bytes[:])
|
copy(output[:32], xA1Bytes[:])
|
||||||
|
|
||||||
yA0Bytes := g.inner.Y.A0.Bytes()
|
xA0Bytes := g.inner.X.A0.Bytes()
|
||||||
copy(output[64:96], yA0Bytes[:])
|
copy(output[32:64], xA0Bytes[:])
|
||||||
|
|
||||||
yA1Bytes := g.inner.Y.A1.Bytes()
|
yA1Bytes := g.inner.Y.A1.Bytes()
|
||||||
copy(output[96:128], yA1Bytes[:])
|
copy(output[64:96], yA1Bytes[:])
|
||||||
|
|
||||||
|
yA0Bytes := g.inner.Y.A0.Bytes()
|
||||||
|
copy(output[96:128], yA0Bytes[:])
|
||||||
|
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ func (c *twistPoint) Set(a *twistPoint) {
|
||||||
c.t.Set(a.t)
|
c.t.Set(a.t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsOnCurve returns true iff c is on the curve where c must be in affine form.
|
// IsOnCurve returns true iff c is on the curve and is in the correct subgroup, where c must be in affine form.
|
||||||
func (c *twistPoint) IsOnCurve() bool {
|
func (c *twistPoint) IsOnCurve() bool {
|
||||||
pool := new(bnPool)
|
pool := new(bnPool)
|
||||||
yy := newGFp2(pool).Square(c.y, pool)
|
yy := newGFp2(pool).Square(c.y, pool)
|
||||||
|
|
@ -80,6 +80,8 @@ func (c *twistPoint) IsOnCurve() bool {
|
||||||
if yy.x.Sign() != 0 || yy.y.Sign() != 0 {
|
if yy.x.Sign() != 0 || yy.y.Sign() != 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
// Subgroup check: multiply the point by the group order and
|
||||||
|
// verify that it becomes the point at infinity.
|
||||||
cneg := newTwistPoint(pool)
|
cneg := newTwistPoint(pool)
|
||||||
cneg.Mul(c, Order, pool)
|
cneg.Mul(c, Order, pool)
|
||||||
return cneg.z.IsZero()
|
return cneg.z.IsZero()
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
|
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
|
||||||
"github.com/ethereum/go-ethereum/core/txpool/locals"
|
"github.com/ethereum/go-ethereum/core/txpool/locals"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
|
|
@ -61,7 +60,7 @@ func initBackend(withLocal bool) *EthAPIBackend {
|
||||||
db = rawdb.NewMemoryDatabase()
|
db = rawdb.NewMemoryDatabase()
|
||||||
engine = beacon.New(ethash.NewFaker())
|
engine = beacon.New(ethash.NewFaker())
|
||||||
)
|
)
|
||||||
chain, _ := core.NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil)
|
chain, _ := core.NewBlockChain(db, gspec, engine, nil)
|
||||||
|
|
||||||
txconfig := legacypool.DefaultConfig
|
txconfig := legacypool.DefaultConfig
|
||||||
txconfig.Journal = "" // Don't litter the disk with test journals
|
txconfig.Journal = "" // Don't litter the disk with test journals
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/triedb"
|
"github.com/ethereum/go-ethereum/triedb"
|
||||||
|
|
@ -68,15 +67,15 @@ func newTestBlockChain(t *testing.T, n int, gspec *core.Genesis, generator func(
|
||||||
_, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, n, generator)
|
_, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, n, generator)
|
||||||
|
|
||||||
// Import the canonical chain
|
// Import the canonical chain
|
||||||
cacheConfig := &core.CacheConfig{
|
options := &core.BlockChainConfig{
|
||||||
TrieCleanLimit: 256,
|
TrieCleanLimit: 256,
|
||||||
TrieDirtyLimit: 256,
|
TrieDirtyLimit: 256,
|
||||||
TrieTimeLimit: 5 * time.Minute,
|
TrieTimeLimit: 5 * time.Minute,
|
||||||
SnapshotLimit: 0,
|
SnapshotLimit: 0,
|
||||||
Preimages: true,
|
Preimages: true,
|
||||||
TrieDirtyDisabled: true, // Archive mode
|
ArchiveMode: true, // Archive mode
|
||||||
}
|
}
|
||||||
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), cacheConfig, gspec, nil, engine, vm.Config{}, nil)
|
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
@ -223,19 +224,22 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||||
vmConfig = vm.Config{
|
vmConfig = vm.Config{
|
||||||
EnablePreimageRecording: config.EnablePreimageRecording,
|
EnablePreimageRecording: config.EnablePreimageRecording,
|
||||||
}
|
}
|
||||||
cacheConfig = &core.CacheConfig{
|
options = &core.BlockChainConfig{
|
||||||
TrieCleanLimit: config.TrieCleanCache,
|
TrieCleanLimit: config.TrieCleanCache,
|
||||||
TrieCleanNoPrefetch: config.NoPrefetch,
|
NoPrefetch: config.NoPrefetch,
|
||||||
TrieDirtyLimit: config.TrieDirtyCache,
|
TrieDirtyLimit: config.TrieDirtyCache,
|
||||||
TrieDirtyDisabled: config.NoPruning,
|
ArchiveMode: config.NoPruning,
|
||||||
TrieTimeLimit: config.TrieTimeout,
|
TrieTimeLimit: config.TrieTimeout,
|
||||||
SnapshotLimit: config.SnapshotCache,
|
SnapshotLimit: config.SnapshotCache,
|
||||||
Preimages: config.Preimages,
|
Preimages: config.Preimages,
|
||||||
StateHistory: config.StateHistory,
|
StateHistory: config.StateHistory,
|
||||||
StateScheme: scheme,
|
StateScheme: scheme,
|
||||||
ChainHistoryMode: config.HistoryMode,
|
ChainHistoryMode: config.HistoryMode,
|
||||||
|
TxLookupLimit: int64(min(config.TransactionHistory, math.MaxInt64)),
|
||||||
|
VmConfig: vmConfig,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if config.VMTrace != "" {
|
if config.VMTrace != "" {
|
||||||
traceConfig := json.RawMessage("{}")
|
traceConfig := json.RawMessage("{}")
|
||||||
if config.VMTraceJsonConfig != "" {
|
if config.VMTraceJsonConfig != "" {
|
||||||
|
|
@ -255,7 +259,9 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||||
if config.OverrideVerkle != nil {
|
if config.OverrideVerkle != nil {
|
||||||
overrides.OverrideVerkle = config.OverrideVerkle
|
overrides.OverrideVerkle = config.OverrideVerkle
|
||||||
}
|
}
|
||||||
eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, &config.TransactionHistory)
|
options.Overrides = &overrides
|
||||||
|
|
||||||
|
eth.blockchain, err = core.NewBlockChain(chainDb, config.Genesis, eth.engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -303,7 +309,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Permit the downloader to use the trie cache allowance during fast sync
|
// Permit the downloader to use the trie cache allowance during fast sync
|
||||||
cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit
|
cacheLimit := options.TrieCleanLimit + options.TrieDirtyLimit + options.SnapshotLimit
|
||||||
if eth.handler, err = newHandler(&handlerConfig{
|
if eth.handler, err = newHandler(&handlerConfig{
|
||||||
NodeID: eth.p2pServer.Self().ID(),
|
NodeID: eth.p2pServer.Self().ID(),
|
||||||
Database: chainDb,
|
Database: chainDb,
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/eth/protocols/eth"
|
"github.com/ethereum/go-ethereum/eth/protocols/eth"
|
||||||
"github.com/ethereum/go-ethereum/eth/protocols/snap"
|
"github.com/ethereum/go-ethereum/eth/protocols/snap"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
|
@ -68,7 +67,7 @@ func newTesterWithNotification(t *testing.T, success func()) *downloadTester {
|
||||||
Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
|
Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
|
||||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||||
}
|
}
|
||||||
chain, err := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
chain, err := core.NewBlockChain(db, gspec, ethash.NewFaker(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/triedb"
|
"github.com/ethereum/go-ethereum/triedb"
|
||||||
|
|
@ -217,7 +216,7 @@ func newTestBlockchain(blocks []*types.Block) *core.BlockChain {
|
||||||
if pregenerated {
|
if pregenerated {
|
||||||
panic("Requested chain generation outside of init")
|
panic("Requested chain generation outside of init")
|
||||||
}
|
}
|
||||||
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, testGspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), testGspec, ethash.NewFaker(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/filtermaps"
|
"github.com/ethereum/go-ethereum/core/filtermaps"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
|
@ -277,8 +276,9 @@ func testFilters(t *testing.T, history uint64, noHistory bool) {
|
||||||
gen.AddTx(tx)
|
gen.AddTx(tx)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
var l uint64
|
options := core.DefaultConfig().WithStateScheme(rawdb.HashScheme)
|
||||||
bc, err := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, &l)
|
options.TxLookupLimit = 0 // index all txs
|
||||||
|
bc, err := core.NewBlockChain(db, gspec, ethash.NewFaker(), options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -434,8 +434,10 @@ func TestRangeLogs(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
chain, _ := core.GenerateChain(gspec.Config, gspec.ToBlock(), ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) {})
|
chain, _ := core.GenerateChain(gspec.Config, gspec.ToBlock(), ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) {})
|
||||||
var l uint64
|
|
||||||
bc, err := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, &l)
|
options := core.DefaultConfig().WithStateScheme(rawdb.HashScheme)
|
||||||
|
options.TxLookupLimit = 0 // index all txs
|
||||||
|
bc, err := core.NewBlockChain(db, gspec, ethash.NewFaker(), options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
|
@ -212,7 +211,7 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, cancunBlock *big.Int, pe
|
||||||
})
|
})
|
||||||
|
|
||||||
// Construct testing chain
|
// Construct testing chain
|
||||||
chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieCleanNoPrefetch: true}, gspec, nil, engine, vm.Config{}, nil)
|
chain, err := core.NewBlockChain(db, gspec, engine, &core.BlockChainConfig{NoPrefetch: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create local chain, %v", err)
|
t.Fatalf("Failed to create local chain, %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||||
"github.com/ethereum/go-ethereum/eth/protocols/eth"
|
"github.com/ethereum/go-ethereum/eth/protocols/eth"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
|
@ -97,8 +96,8 @@ func testForkIDSplit(t *testing.T, protocol uint) {
|
||||||
gspecNoFork = &core.Genesis{Config: configNoFork}
|
gspecNoFork = &core.Genesis{Config: configNoFork}
|
||||||
gspecProFork = &core.Genesis{Config: configProFork}
|
gspecProFork = &core.Genesis{Config: configProFork}
|
||||||
|
|
||||||
chainNoFork, _ = core.NewBlockChain(dbNoFork, nil, gspecNoFork, nil, engine, vm.Config{}, nil)
|
chainNoFork, _ = core.NewBlockChain(dbNoFork, gspecNoFork, engine, nil)
|
||||||
chainProFork, _ = core.NewBlockChain(dbProFork, nil, gspecProFork, nil, engine, vm.Config{}, nil)
|
chainProFork, _ = core.NewBlockChain(dbProFork, gspecProFork, engine, nil)
|
||||||
|
|
||||||
_, blocksNoFork, _ = core.GenerateChainWithGenesis(gspecNoFork, engine, 2, nil)
|
_, blocksNoFork, _ = core.GenerateChainWithGenesis(gspecNoFork, engine, 2, nil)
|
||||||
_, blocksProFork, _ = core.GenerateChainWithGenesis(gspecProFork, engine, 2, nil)
|
_, blocksProFork, _ = core.GenerateChainWithGenesis(gspecProFork, engine, 2, nil)
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/txpool"
|
"github.com/ethereum/go-ethereum/core/txpool"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
|
@ -182,7 +181,7 @@ func newTestHandlerWithBlocks(blocks int) *testHandler {
|
||||||
Config: params.TestChainConfig,
|
Config: params.TestChainConfig,
|
||||||
Alloc: types.GenesisAlloc{testAddr: {Balance: big.NewInt(1000000)}},
|
Alloc: types.GenesisAlloc{testAddr: {Balance: big.NewInt(1000000)}},
|
||||||
}
|
}
|
||||||
chain, _ := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
chain, _ := core.NewBlockChain(db, gspec, ethash.NewFaker(), nil)
|
||||||
|
|
||||||
_, bs, _ := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), blocks, nil)
|
_, bs, _ := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), blocks, nil)
|
||||||
if _, err := chain.InsertChain(bs); err != nil {
|
if _, err := chain.InsertChain(bs); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/txpool/blobpool"
|
"github.com/ethereum/go-ethereum/core/txpool/blobpool"
|
||||||
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
|
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
|
@ -120,7 +119,7 @@ func newTestBackendWithGenerator(blocks int, shanghai bool, cancun bool, generat
|
||||||
Alloc: types.GenesisAlloc{testAddr: {Balance: big.NewInt(100_000_000_000_000_000)}},
|
Alloc: types.GenesisAlloc{testAddr: {Balance: big.NewInt(100_000_000_000_000_000)}},
|
||||||
Difficulty: common.Big0,
|
Difficulty: common.Big0,
|
||||||
}
|
}
|
||||||
chain, _ := core.NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil)
|
chain, _ := core.NewBlockChain(db, gspec, engine, nil)
|
||||||
|
|
||||||
_, bs, _ := core.GenerateChainWithGenesis(gspec, engine, blocks, generator)
|
_, bs, _ := core.GenerateChainWithGenesis(gspec, engine, blocks, generator)
|
||||||
if _, err := chain.InsertChain(bs); err != nil {
|
if _, err := chain.InsertChain(bs); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -117,16 +116,16 @@ func getChain() *core.BlockChain {
|
||||||
Alloc: ga,
|
Alloc: ga,
|
||||||
}
|
}
|
||||||
_, blocks, _ := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), 2, func(i int, gen *core.BlockGen) {})
|
_, blocks, _ := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), 2, func(i int, gen *core.BlockGen) {})
|
||||||
cacheConf := &core.CacheConfig{
|
options := &core.BlockChainConfig{
|
||||||
TrieCleanLimit: 0,
|
TrieCleanLimit: 0,
|
||||||
TrieDirtyLimit: 0,
|
TrieDirtyLimit: 0,
|
||||||
TrieTimeLimit: 5 * time.Minute,
|
TrieTimeLimit: 5 * time.Minute,
|
||||||
TrieCleanNoPrefetch: true,
|
NoPrefetch: true,
|
||||||
SnapshotLimit: 100,
|
SnapshotLimit: 100,
|
||||||
SnapshotWait: true,
|
SnapshotWait: true,
|
||||||
}
|
}
|
||||||
trieRoot = blocks[len(blocks)-1].Root()
|
trieRoot = blocks[len(blocks)-1].Root()
|
||||||
bc, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), cacheConf, gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
bc, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), gspec, ethash.NewFaker(), options)
|
||||||
if _, err := bc.InsertChain(blocks); err != nil {
|
if _, err := bc.InsertChain(blocks); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,14 +77,14 @@ func newTestBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i i
|
||||||
_, blocks, _ := core.GenerateChainWithGenesis(gspec, backend.engine, n, generator)
|
_, blocks, _ := core.GenerateChainWithGenesis(gspec, backend.engine, n, generator)
|
||||||
|
|
||||||
// Import the canonical chain
|
// Import the canonical chain
|
||||||
cacheConfig := &core.CacheConfig{
|
options := &core.BlockChainConfig{
|
||||||
TrieCleanLimit: 256,
|
TrieCleanLimit: 256,
|
||||||
TrieDirtyLimit: 256,
|
TrieDirtyLimit: 256,
|
||||||
TrieTimeLimit: 5 * time.Minute,
|
TrieTimeLimit: 5 * time.Minute,
|
||||||
SnapshotLimit: 0,
|
SnapshotLimit: 0,
|
||||||
TrieDirtyDisabled: true, // Archive mode
|
ArchiveMode: true, // Archive mode
|
||||||
}
|
}
|
||||||
chain, err := core.NewBlockChain(backend.chaindb, cacheConfig, gspec, nil, backend.engine, vm.Config{}, nil)
|
chain, err := core.NewBlockChain(backend.chaindb, gspec, backend.engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1144,14 +1144,14 @@ func newTestMergedBackend(t *testing.T, n int, gspec *core.Genesis, generator fu
|
||||||
_, blocks, _ := core.GenerateChainWithGenesis(gspec, backend.engine, n, generator)
|
_, blocks, _ := core.GenerateChainWithGenesis(gspec, backend.engine, n, generator)
|
||||||
|
|
||||||
// Import the canonical chain
|
// Import the canonical chain
|
||||||
cacheConfig := &core.CacheConfig{
|
options := &core.BlockChainConfig{
|
||||||
TrieCleanLimit: 256,
|
TrieCleanLimit: 256,
|
||||||
TrieDirtyLimit: 256,
|
TrieDirtyLimit: 256,
|
||||||
TrieTimeLimit: 5 * time.Minute,
|
TrieTimeLimit: 5 * time.Minute,
|
||||||
SnapshotLimit: 0,
|
SnapshotLimit: 0,
|
||||||
TrieDirtyDisabled: true, // Archive mode
|
ArchiveMode: true, // Archive mode
|
||||||
}
|
}
|
||||||
chain, err := core.NewBlockChain(backend.chaindb, cacheConfig, gspec, nil, backend.engine, vm.Config{}, nil)
|
chain, err := core.NewBlockChain(backend.chaindb, gspec, backend.engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -554,7 +554,9 @@ func testSupplyTracer(t *testing.T, genesis *core.Genesis, gen func(*core.BlockG
|
||||||
return nil, nil, fmt.Errorf("failed to create call tracer: %v", err)
|
return nil, nil, fmt.Errorf("failed to create call tracer: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), core.DefaultCacheConfigWithScheme(rawdb.PathScheme), genesis, nil, engine, vm.Config{Tracer: tracer}, nil)
|
options := core.DefaultConfig().WithStateScheme(rawdb.PathScheme)
|
||||||
|
options.VmConfig = vm.Config{Tracer: tracer}
|
||||||
|
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), genesis, engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("failed to create tester chain: %v", err)
|
return nil, nil, fmt.Errorf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ const IdealBatchSize = 100 * 1024
|
||||||
// when Write is called. A batch cannot be used concurrently.
|
// when Write is called. A batch cannot be used concurrently.
|
||||||
type Batch interface {
|
type Batch interface {
|
||||||
KeyValueWriter
|
KeyValueWriter
|
||||||
|
KeyValueRangeDeleter
|
||||||
|
|
||||||
// ValueSize retrieves the amount of data queued up for writing.
|
// ValueSize retrieves the amount of data queued up for writing.
|
||||||
ValueSize() int
|
ValueSize() int
|
||||||
|
|
@ -53,8 +54,9 @@ type Batcher interface {
|
||||||
type HookedBatch struct {
|
type HookedBatch struct {
|
||||||
Batch
|
Batch
|
||||||
|
|
||||||
OnPut func(key []byte, value []byte) // Callback if a key is inserted
|
OnPut func(key []byte, value []byte) // Callback if a key is inserted
|
||||||
OnDelete func(key []byte) // Callback if a key is deleted
|
OnDelete func(key []byte) // Callback if a key is deleted
|
||||||
|
OnDeleteRange func(start, end []byte) // Callback if a range of keys is deleted
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put inserts the given value into the key-value data store.
|
// Put inserts the given value into the key-value data store.
|
||||||
|
|
@ -72,3 +74,11 @@ func (b HookedBatch) Delete(key []byte) error {
|
||||||
}
|
}
|
||||||
return b.Batch.Delete(key)
|
return b.Batch.Delete(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteRange removes all keys in the range [start, end) from the key-value data store.
|
||||||
|
func (b HookedBatch) DeleteRange(start, end []byte) error {
|
||||||
|
if b.OnDeleteRange != nil {
|
||||||
|
b.OnDeleteRange(start, end)
|
||||||
|
}
|
||||||
|
return b.Batch.DeleteRange(start, end)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,23 @@
|
||||||
package ethdb
|
package ethdb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// MaximumKey is a special marker representing the largest possible key
|
||||||
|
// in the database.
|
||||||
|
//
|
||||||
|
// All prefixed database entries will be smaller than this marker.
|
||||||
|
// For trie nodes in hash mode, we use a 32-byte slice filled with 0xFF
|
||||||
|
// because there may be shared prefixes starting with multiple 0xFF bytes.
|
||||||
|
// Using 32 bytes ensures that only a hash collision could potentially
|
||||||
|
// match or exceed it.
|
||||||
|
MaximumKey = bytes.Repeat([]byte{0xff}, 32)
|
||||||
|
)
|
||||||
|
|
||||||
// KeyValueReader wraps the Has and Get method of a backing data store.
|
// KeyValueReader wraps the Has and Get method of a backing data store.
|
||||||
type KeyValueReader interface {
|
type KeyValueReader interface {
|
||||||
// Has retrieves if a key is present in the key-value data store.
|
// Has retrieves if a key is present in the key-value data store.
|
||||||
|
|
@ -46,6 +59,11 @@ var ErrTooManyKeys = errors.New("too many keys in deleted range")
|
||||||
type KeyValueRangeDeleter interface {
|
type KeyValueRangeDeleter interface {
|
||||||
// DeleteRange deletes all of the keys (and values) in the range [start,end)
|
// DeleteRange deletes all of the keys (and values) in the range [start,end)
|
||||||
// (inclusive on start, exclusive on end).
|
// (inclusive on start, exclusive on end).
|
||||||
|
//
|
||||||
|
// A nil start is treated as a key before all keys in the data store; a nil
|
||||||
|
// end is treated as a key after all keys in the data store. If both is nil
|
||||||
|
// then the entire data store will be purged.
|
||||||
|
//
|
||||||
// Some implementations of DeleteRange may return ErrTooManyKeys after
|
// Some implementations of DeleteRange may return ErrTooManyKeys after
|
||||||
// partially deleting entries in the given range.
|
// partially deleting entries in the given range.
|
||||||
DeleteRange(start, end []byte) error
|
DeleteRange(start, end []byte) error
|
||||||
|
|
|
||||||
|
|
@ -401,6 +401,308 @@ func TestDatabaseSuite(t *testing.T, New func() ethdb.KeyValueStore) {
|
||||||
|
|
||||||
db.DeleteRange([]byte(""), []byte("a"))
|
db.DeleteRange([]byte(""), []byte("a"))
|
||||||
checkRange(1, 999, false)
|
checkRange(1, 999, false)
|
||||||
|
|
||||||
|
addRange(1, 999)
|
||||||
|
db.DeleteRange(nil, nil)
|
||||||
|
checkRange(1, 999, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("BatchDeleteRange", func(t *testing.T) {
|
||||||
|
db := New()
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
// Helper to add keys
|
||||||
|
addKeys := func(start, stop int) {
|
||||||
|
for i := start; i <= stop; i++ {
|
||||||
|
if err := db.Put([]byte(strconv.Itoa(i)), []byte("val-"+strconv.Itoa(i))); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to check if keys exist
|
||||||
|
checkKeys := func(start, stop int, shouldExist bool) {
|
||||||
|
for i := start; i <= stop; i++ {
|
||||||
|
key := []byte(strconv.Itoa(i))
|
||||||
|
has, err := db.Has(key)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if has != shouldExist {
|
||||||
|
if shouldExist {
|
||||||
|
t.Fatalf("key %s should exist but doesn't", key)
|
||||||
|
} else {
|
||||||
|
t.Fatalf("key %s shouldn't exist but does", key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test 1: Basic range deletion in batch
|
||||||
|
addKeys(1, 10)
|
||||||
|
checkKeys(1, 10, true)
|
||||||
|
|
||||||
|
batch := db.NewBatch()
|
||||||
|
if err := batch.DeleteRange([]byte("3"), []byte("8")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// Keys shouldn't be deleted until Write is called
|
||||||
|
checkKeys(1, 10, true)
|
||||||
|
|
||||||
|
if err := batch.Write(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// After Write, keys in range should be deleted
|
||||||
|
// Range is [start, end) - inclusive of start, exclusive of end
|
||||||
|
checkKeys(1, 2, true) // These should still exist
|
||||||
|
checkKeys(3, 7, false) // These should be deleted (3 to 7 inclusive)
|
||||||
|
checkKeys(8, 10, true) // These should still exist (8 is the end boundary, exclusive)
|
||||||
|
|
||||||
|
// Test 2: Delete range with special markers
|
||||||
|
addKeys(3, 7)
|
||||||
|
batch = db.NewBatch()
|
||||||
|
if err := batch.DeleteRange(nil, nil); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := batch.Write(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
checkKeys(1, 10, false)
|
||||||
|
|
||||||
|
// Test 3: Mix Put, Delete, and DeleteRange in a batch
|
||||||
|
// Reset database for next test by adding back deleted keys
|
||||||
|
addKeys(1, 10)
|
||||||
|
checkKeys(1, 10, true)
|
||||||
|
|
||||||
|
// Create a new batch with multiple operations
|
||||||
|
batch = db.NewBatch()
|
||||||
|
if err := batch.Put([]byte("5"), []byte("new-val-5")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := batch.Delete([]byte("9")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := batch.DeleteRange([]byte("1"), []byte("3")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := batch.Write(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// Check results after batch operations
|
||||||
|
// Keys 1-2 should be deleted by DeleteRange
|
||||||
|
checkKeys(1, 2, false)
|
||||||
|
|
||||||
|
// Key 3 should exist (exclusive of end)
|
||||||
|
has, err := db.Has([]byte("3"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !has {
|
||||||
|
t.Fatalf("key 3 should exist after DeleteRange(1,3)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key 5 should have a new value
|
||||||
|
val, err := db.Get([]byte("5"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(val, []byte("new-val-5")) {
|
||||||
|
t.Fatalf("key 5 has wrong value: got %s, want %s", val, "new-val-5")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key 9 should be deleted
|
||||||
|
has, err = db.Has([]byte("9"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if has {
|
||||||
|
t.Fatalf("key 9 should be deleted")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test 4: Reset batch
|
||||||
|
batch.Reset()
|
||||||
|
// Individual deletes work better with both string and numeric comparisons
|
||||||
|
if err := batch.Delete([]byte("8")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := batch.Delete([]byte("10")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := batch.Delete([]byte("11")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := batch.Write(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key 8 should be deleted
|
||||||
|
has, err = db.Has([]byte("8"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if has {
|
||||||
|
t.Fatalf("key 8 should be deleted")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys 3-7 should still exist
|
||||||
|
checkKeys(3, 7, true)
|
||||||
|
|
||||||
|
// Key 10 should be deleted
|
||||||
|
has, err = db.Has([]byte("10"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if has {
|
||||||
|
t.Fatalf("key 10 should be deleted")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test 5: Empty range
|
||||||
|
batch = db.NewBatch()
|
||||||
|
if err := batch.DeleteRange([]byte("100"), []byte("100")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := batch.Write(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// No existing keys should be affected
|
||||||
|
checkKeys(3, 7, true)
|
||||||
|
|
||||||
|
// Test 6: Test entire keyspace deletion
|
||||||
|
// First clear any existing keys
|
||||||
|
for i := 1; i <= 100; i++ {
|
||||||
|
db.Delete([]byte(strconv.Itoa(i)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then add some fresh test keys
|
||||||
|
addKeys(50, 60)
|
||||||
|
|
||||||
|
// Verify keys exist before deletion
|
||||||
|
checkKeys(50, 60, true)
|
||||||
|
|
||||||
|
batch = db.NewBatch()
|
||||||
|
if err := batch.DeleteRange([]byte(""), []byte("z")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := batch.Write(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// All keys should be deleted
|
||||||
|
checkKeys(50, 60, false)
|
||||||
|
|
||||||
|
// Test 7: overlapping range deletion
|
||||||
|
addKeys(50, 60)
|
||||||
|
batch = db.NewBatch()
|
||||||
|
if err := batch.DeleteRange([]byte("50"), []byte("55")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := batch.DeleteRange([]byte("52"), []byte("58")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := batch.Write(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
checkKeys(50, 57, false)
|
||||||
|
checkKeys(58, 60, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("BatchReplayWithDeleteRange", func(t *testing.T) {
|
||||||
|
db := New()
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
// Setup some initial data
|
||||||
|
for i := 1; i <= 10; i++ {
|
||||||
|
if err := db.Put([]byte(strconv.Itoa(i)), []byte("val-"+strconv.Itoa(i))); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create batch with multiple operations including DeleteRange
|
||||||
|
batch1 := db.NewBatch()
|
||||||
|
batch1.Put([]byte("new-key-1"), []byte("new-val-1"))
|
||||||
|
batch1.DeleteRange([]byte("3"), []byte("7")) // Should delete keys 3-6 but not 7
|
||||||
|
batch1.Delete([]byte("8"))
|
||||||
|
batch1.Put([]byte("new-key-2"), []byte("new-val-2"))
|
||||||
|
|
||||||
|
// Create a second batch to replay into
|
||||||
|
batch2 := db.NewBatch()
|
||||||
|
if err := batch1.Replay(batch2); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the second batch
|
||||||
|
if err := batch2.Write(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify results
|
||||||
|
// Original keys 3-6 should be deleted (inclusive of start, exclusive of end)
|
||||||
|
for i := 3; i <= 6; i++ {
|
||||||
|
has, err := db.Has([]byte(strconv.Itoa(i)))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if has {
|
||||||
|
t.Fatalf("key %d should be deleted", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key 7 should NOT be deleted (exclusive of end)
|
||||||
|
has, err := db.Has([]byte("7"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !has {
|
||||||
|
t.Fatalf("key 7 should NOT be deleted (exclusive of end)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key 8 should be deleted
|
||||||
|
has, err = db.Has([]byte("8"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if has {
|
||||||
|
t.Fatalf("key 8 should be deleted")
|
||||||
|
}
|
||||||
|
|
||||||
|
// New keys should be added
|
||||||
|
for _, key := range []string{"new-key-1", "new-key-2"} {
|
||||||
|
has, err := db.Has([]byte(key))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !has {
|
||||||
|
t.Fatalf("key %s should exist", key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a third batch for direct replay to database
|
||||||
|
batch3 := db.NewBatch()
|
||||||
|
batch3.DeleteRange([]byte("1"), []byte("3")) // Should delete keys 1-2 but not 3
|
||||||
|
|
||||||
|
// Replay directly to the database
|
||||||
|
if err := batch3.Replay(db); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify keys 1-2 are now deleted
|
||||||
|
for i := 1; i <= 2; i++ {
|
||||||
|
has, err := db.Has([]byte(strconv.Itoa(i)))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if has {
|
||||||
|
t.Fatalf("key %d should be deleted after direct replay", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify key 3 is NOT deleted (since it's exclusive of end)
|
||||||
|
has, err = db.Has([]byte("3"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if has {
|
||||||
|
t.Fatalf("key 3 should still be deleted from previous operation")
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -520,6 +822,81 @@ func BenchDatabaseSuite(b *testing.B, New func() ethdb.KeyValueStore) {
|
||||||
benchDeleteRange(b, 10000)
|
benchDeleteRange(b, 10000)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
b.Run("BatchDeleteRange", func(b *testing.B) {
|
||||||
|
benchBatchDeleteRange := func(b *testing.B, count int) {
|
||||||
|
db := New()
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
// Prepare data
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
db.Put([]byte(strconv.Itoa(i)), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
b.ReportAllocs()
|
||||||
|
|
||||||
|
// Create batch and delete range
|
||||||
|
batch := db.NewBatch()
|
||||||
|
batch.DeleteRange([]byte("0"), []byte("999999999"))
|
||||||
|
batch.Write()
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Run("BatchDeleteRange100", func(b *testing.B) {
|
||||||
|
benchBatchDeleteRange(b, 100)
|
||||||
|
})
|
||||||
|
b.Run("BatchDeleteRange1k", func(b *testing.B) {
|
||||||
|
benchBatchDeleteRange(b, 1000)
|
||||||
|
})
|
||||||
|
b.Run("BatchDeleteRange10k", func(b *testing.B) {
|
||||||
|
benchBatchDeleteRange(b, 10000)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("BatchMixedOps", func(b *testing.B) {
|
||||||
|
benchBatchMixedOps := func(b *testing.B, count int) {
|
||||||
|
db := New()
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
// Prepare initial data
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
db.Put([]byte(strconv.Itoa(i)), []byte("val"))
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
b.ReportAllocs()
|
||||||
|
|
||||||
|
// Create batch with mixed operations
|
||||||
|
batch := db.NewBatch()
|
||||||
|
|
||||||
|
// Add some new keys
|
||||||
|
for i := 0; i < count/10; i++ {
|
||||||
|
batch.Put([]byte(strconv.Itoa(count+i)), []byte("new-val"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete some individual keys
|
||||||
|
for i := 0; i < count/20; i++ {
|
||||||
|
batch.Delete([]byte(strconv.Itoa(i * 2)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete range of keys
|
||||||
|
rangeStart := count / 2
|
||||||
|
rangeEnd := count * 3 / 4
|
||||||
|
batch.DeleteRange([]byte(strconv.Itoa(rangeStart)), []byte(strconv.Itoa(rangeEnd)))
|
||||||
|
|
||||||
|
// Write the batch
|
||||||
|
batch.Write()
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Run("BatchMixedOps100", func(b *testing.B) {
|
||||||
|
benchBatchMixedOps(b, 100)
|
||||||
|
})
|
||||||
|
b.Run("BatchMixedOps1k", func(b *testing.B) {
|
||||||
|
benchBatchMixedOps(b, 1000)
|
||||||
|
})
|
||||||
|
b.Run("BatchMixedOps10k", func(b *testing.B) {
|
||||||
|
benchBatchMixedOps(b, 10000)
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func iterateKeys(it ethdb.Iterator) []string {
|
func iterateKeys(it ethdb.Iterator) []string {
|
||||||
|
|
|
||||||
|
|
@ -220,7 +220,7 @@ func (db *Database) DeleteRange(start, end []byte) error {
|
||||||
defer it.Release()
|
defer it.Release()
|
||||||
|
|
||||||
var count int
|
var count int
|
||||||
for it.Next() && bytes.Compare(end, it.Key()) > 0 {
|
for it.Next() && (end == nil || bytes.Compare(end, it.Key()) > 0) {
|
||||||
count++
|
count++
|
||||||
if count > 10000 { // should not block for more than a second
|
if count > 10000 { // should not block for more than a second
|
||||||
if err := batch.Write(); err != nil {
|
if err := batch.Write(); err != nil {
|
||||||
|
|
@ -461,6 +461,38 @@ func (b *batch) Delete(key []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteRange removes all keys in the range [start, end) from the batch for
|
||||||
|
// later committing, inclusive on start, exclusive on end.
|
||||||
|
//
|
||||||
|
// Note that this is a fallback implementation as leveldb does not natively
|
||||||
|
// support range deletion in batches. It iterates through the database to find
|
||||||
|
// keys in the range and adds them to the batch for deletion.
|
||||||
|
func (b *batch) DeleteRange(start, end []byte) error {
|
||||||
|
// Create an iterator to scan through the keys in the range
|
||||||
|
slice := &util.Range{
|
||||||
|
Start: start, // If nil, it represents the key before all keys
|
||||||
|
Limit: end, // If nil, it represents the key after all keys
|
||||||
|
}
|
||||||
|
it := b.db.NewIterator(slice, nil)
|
||||||
|
defer it.Release()
|
||||||
|
|
||||||
|
var count int
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
key := it.Key()
|
||||||
|
if count > 10000 { // should not block for more than a second
|
||||||
|
return ethdb.ErrTooManyKeys
|
||||||
|
}
|
||||||
|
// Add this key to the batch for deletion
|
||||||
|
b.b.Delete(key)
|
||||||
|
b.size += len(key)
|
||||||
|
}
|
||||||
|
if err := it.Error(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ValueSize retrieves the amount of data queued up for writing.
|
// ValueSize retrieves the amount of data queued up for writing.
|
||||||
func (b *batch) ValueSize() int {
|
func (b *batch) ValueSize() int {
|
||||||
return b.size
|
return b.size
|
||||||
|
|
@ -506,6 +538,20 @@ func (r *replayer) Delete(key []byte) {
|
||||||
r.failure = r.writer.Delete(key)
|
r.failure = r.writer.Delete(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteRange removes all keys in the range [start, end) from the key-value data store.
|
||||||
|
func (r *replayer) DeleteRange(start, end []byte) {
|
||||||
|
// If the replay already failed, stop executing ops
|
||||||
|
if r.failure != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Check if the writer also supports range deletion
|
||||||
|
if rangeDeleter, ok := r.writer.(ethdb.KeyValueRangeDeleter); ok {
|
||||||
|
r.failure = rangeDeleter.DeleteRange(start, end)
|
||||||
|
} else {
|
||||||
|
r.failure = fmt.Errorf("ethdb.KeyValueWriter does not implement DeleteRange")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// bytesPrefixRange returns key range that satisfy
|
// bytesPrefixRange returns key range that satisfy
|
||||||
// - the given prefix, and
|
// - the given prefix, and
|
||||||
// - the given seek position
|
// - the given seek position
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,9 @@
|
||||||
package memorydb
|
package memorydb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
@ -122,18 +124,24 @@ func (db *Database) Delete(key []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRange deletes all of the keys (and values) in the range [start,end)
|
// DeleteRange deletes all of the keys (and values) in the range [start,end)
|
||||||
// (inclusive on start, exclusive on end).
|
// (inclusive on start, exclusive on end). If the start is nil, it represents
|
||||||
|
// the key before all keys; if the end is nil, it represents the key after
|
||||||
|
// all keys.
|
||||||
func (db *Database) DeleteRange(start, end []byte) error {
|
func (db *Database) DeleteRange(start, end []byte) error {
|
||||||
db.lock.Lock()
|
db.lock.Lock()
|
||||||
defer db.lock.Unlock()
|
defer db.lock.Unlock()
|
||||||
|
|
||||||
if db.db == nil {
|
if db.db == nil {
|
||||||
return errMemorydbClosed
|
return errMemorydbClosed
|
||||||
}
|
}
|
||||||
|
|
||||||
for key := range db.db {
|
for key := range db.db {
|
||||||
if key >= string(start) && key < string(end) {
|
if start != nil && key < string(start) {
|
||||||
delete(db.db, key)
|
continue
|
||||||
}
|
}
|
||||||
|
if end != nil && key >= string(end) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
delete(db.db, key)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -222,6 +230,9 @@ type keyvalue struct {
|
||||||
key string
|
key string
|
||||||
value []byte
|
value []byte
|
||||||
delete bool
|
delete bool
|
||||||
|
|
||||||
|
rangeFrom []byte
|
||||||
|
rangeTo []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// batch is a write-only memory batch that commits changes to its host
|
// batch is a write-only memory batch that commits changes to its host
|
||||||
|
|
@ -234,18 +245,29 @@ type batch struct {
|
||||||
|
|
||||||
// Put inserts the given value into the batch for later committing.
|
// Put inserts the given value into the batch for later committing.
|
||||||
func (b *batch) Put(key, value []byte) error {
|
func (b *batch) Put(key, value []byte) error {
|
||||||
b.writes = append(b.writes, keyvalue{string(key), common.CopyBytes(value), false})
|
b.writes = append(b.writes, keyvalue{key: string(key), value: common.CopyBytes(value)})
|
||||||
b.size += len(key) + len(value)
|
b.size += len(key) + len(value)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete inserts the key removal into the batch for later committing.
|
// Delete inserts the key removal into the batch for later committing.
|
||||||
func (b *batch) Delete(key []byte) error {
|
func (b *batch) Delete(key []byte) error {
|
||||||
b.writes = append(b.writes, keyvalue{string(key), nil, true})
|
b.writes = append(b.writes, keyvalue{key: string(key), delete: true})
|
||||||
b.size += len(key)
|
b.size += len(key)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteRange removes all keys in the range [start, end) from the batch for later committing.
|
||||||
|
func (b *batch) DeleteRange(start, end []byte) error {
|
||||||
|
b.writes = append(b.writes, keyvalue{
|
||||||
|
rangeFrom: bytes.Clone(start),
|
||||||
|
rangeTo: bytes.Clone(end),
|
||||||
|
delete: true,
|
||||||
|
})
|
||||||
|
b.size += len(start) + len(end)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ValueSize retrieves the amount of data queued up for writing.
|
// ValueSize retrieves the amount of data queued up for writing.
|
||||||
func (b *batch) ValueSize() int {
|
func (b *batch) ValueSize() int {
|
||||||
return b.size
|
return b.size
|
||||||
|
|
@ -259,12 +281,26 @@ func (b *batch) Write() error {
|
||||||
if b.db.db == nil {
|
if b.db.db == nil {
|
||||||
return errMemorydbClosed
|
return errMemorydbClosed
|
||||||
}
|
}
|
||||||
for _, keyvalue := range b.writes {
|
for _, entry := range b.writes {
|
||||||
if keyvalue.delete {
|
if entry.delete {
|
||||||
delete(b.db.db, keyvalue.key)
|
if entry.key != "" {
|
||||||
|
// Single key deletion
|
||||||
|
delete(b.db.db, entry.key)
|
||||||
|
} else {
|
||||||
|
// Range deletion (inclusive of start, exclusive of end)
|
||||||
|
for key := range b.db.db {
|
||||||
|
if entry.rangeFrom != nil && key < string(entry.rangeFrom) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if entry.rangeTo != nil && key >= string(entry.rangeTo) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
delete(b.db.db, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
b.db.db[keyvalue.key] = keyvalue.value
|
b.db.db[entry.key] = entry.value
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -277,14 +313,26 @@ func (b *batch) Reset() {
|
||||||
|
|
||||||
// Replay replays the batch contents.
|
// Replay replays the batch contents.
|
||||||
func (b *batch) Replay(w ethdb.KeyValueWriter) error {
|
func (b *batch) Replay(w ethdb.KeyValueWriter) error {
|
||||||
for _, keyvalue := range b.writes {
|
for _, entry := range b.writes {
|
||||||
if keyvalue.delete {
|
if entry.delete {
|
||||||
if err := w.Delete([]byte(keyvalue.key)); err != nil {
|
if entry.key != "" {
|
||||||
return err
|
// Single key deletion
|
||||||
|
if err := w.Delete([]byte(entry.key)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Range deletion
|
||||||
|
if rangeDeleter, ok := w.(ethdb.KeyValueRangeDeleter); ok {
|
||||||
|
if err := rangeDeleter.DeleteRange(entry.rangeFrom, entry.rangeTo); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("ethdb.KeyValueWriter does not implement DeleteRange")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := w.Put([]byte(keyvalue.key), keyvalue.value); err != nil {
|
if err := w.Put([]byte(entry.key), entry.value); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
package pebble
|
package pebble
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -417,9 +416,16 @@ func (d *Database) Delete(key []byte) error {
|
||||||
func (d *Database) DeleteRange(start, end []byte) error {
|
func (d *Database) DeleteRange(start, end []byte) error {
|
||||||
d.quitLock.RLock()
|
d.quitLock.RLock()
|
||||||
defer d.quitLock.RUnlock()
|
defer d.quitLock.RUnlock()
|
||||||
|
|
||||||
if d.closed {
|
if d.closed {
|
||||||
return pebble.ErrClosed
|
return pebble.ErrClosed
|
||||||
}
|
}
|
||||||
|
// There is no special flag to represent the end of key range
|
||||||
|
// in pebble(nil in leveldb). Use an ugly hack to construct a
|
||||||
|
// large key to represent it.
|
||||||
|
if end == nil {
|
||||||
|
end = ethdb.MaximumKey
|
||||||
|
}
|
||||||
return d.db.DeleteRange(start, end, d.writeOptions)
|
return d.db.DeleteRange(start, end, d.writeOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -478,7 +484,7 @@ func (d *Database) Compact(start []byte, limit []byte) error {
|
||||||
// 0xff-s, so 32 ensures than only a hash collision could touch it.
|
// 0xff-s, so 32 ensures than only a hash collision could touch it.
|
||||||
// https://github.com/cockroachdb/pebble/issues/2359#issuecomment-1443995833
|
// https://github.com/cockroachdb/pebble/issues/2359#issuecomment-1443995833
|
||||||
if limit == nil {
|
if limit == nil {
|
||||||
limit = bytes.Repeat([]byte{0xff}, 32)
|
limit = ethdb.MaximumKey
|
||||||
}
|
}
|
||||||
return d.db.Compact(start, limit, true) // Parallelization is preferred
|
return d.db.Compact(start, limit, true) // Parallelization is preferred
|
||||||
}
|
}
|
||||||
|
|
@ -633,6 +639,23 @@ func (b *batch) Delete(key []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteRange removes all keys in the range [start, end) from the batch for
|
||||||
|
// later committing, inclusive on start, exclusive on end.
|
||||||
|
func (b *batch) DeleteRange(start, end []byte) error {
|
||||||
|
// There is no special flag to represent the end of key range
|
||||||
|
// in pebble(nil in leveldb). Use an ugly hack to construct a
|
||||||
|
// large key to represent it.
|
||||||
|
if end == nil {
|
||||||
|
end = ethdb.MaximumKey
|
||||||
|
}
|
||||||
|
if err := b.b.DeleteRange(start, end, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Approximate size impact - just the keys
|
||||||
|
b.size += len(start) + len(end)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ValueSize retrieves the amount of data queued up for writing.
|
// ValueSize retrieves the amount of data queued up for writing.
|
||||||
func (b *batch) ValueSize() int {
|
func (b *batch) ValueSize() int {
|
||||||
return b.size
|
return b.size
|
||||||
|
|
@ -672,6 +695,15 @@ func (b *batch) Replay(w ethdb.KeyValueWriter) error {
|
||||||
if err = w.Delete(k); err != nil {
|
if err = w.Delete(k); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
} else if kind == pebble.InternalKeyKindRangeDelete {
|
||||||
|
// For range deletion, k is the start key and v is the end key
|
||||||
|
if rangeDeleter, ok := w.(ethdb.KeyValueRangeDeleter); ok {
|
||||||
|
if err = rangeDeleter.DeleteRange(k, v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("ethdb.KeyValueWriter does not implement DeleteRange")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("unhandled operation, keytype: %v", kind)
|
return fmt.Errorf("unhandled operation, keytype: %v", kind)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -442,21 +442,16 @@ type testBackend struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestBackend(t *testing.T, n int, gspec *core.Genesis, engine consensus.Engine, generator func(i int, b *core.BlockGen)) *testBackend {
|
func newTestBackend(t *testing.T, n int, gspec *core.Genesis, engine consensus.Engine, generator func(i int, b *core.BlockGen)) *testBackend {
|
||||||
var (
|
options := core.DefaultConfig().WithArchive(true)
|
||||||
cacheConfig = &core.CacheConfig{
|
options.TxLookupLimit = 0 // index all txs
|
||||||
TrieCleanLimit: 256,
|
|
||||||
TrieDirtyLimit: 256,
|
|
||||||
TrieTimeLimit: 5 * time.Minute,
|
|
||||||
SnapshotLimit: 0,
|
|
||||||
TrieDirtyDisabled: true, // Archive mode
|
|
||||||
}
|
|
||||||
)
|
|
||||||
accman, acc := newTestAccountManager(t)
|
accman, acc := newTestAccountManager(t)
|
||||||
gspec.Alloc[acc.Address] = types.Account{Balance: big.NewInt(params.Ether)}
|
gspec.Alloc[acc.Address] = types.Account{Balance: big.NewInt(params.Ether)}
|
||||||
|
|
||||||
// Generate blocks for testing
|
// Generate blocks for testing
|
||||||
db, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, n, generator)
|
db, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, n, generator)
|
||||||
txlookupLimit := uint64(0)
|
|
||||||
chain, err := core.NewBlockChain(db, cacheConfig, gspec, nil, engine, vm.Config{}, &txlookupLimit)
|
chain, err := core.NewBlockChain(db, gspec, engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/txpool"
|
"github.com/ethereum/go-ethereum/core/txpool"
|
||||||
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
|
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -152,7 +151,7 @@ func createMiner(t *testing.T) *Miner {
|
||||||
// Create consensus engine
|
// Create consensus engine
|
||||||
engine := clique.New(chainConfig.Clique, chainDB)
|
engine := clique.New(chainConfig.Clique, chainDB)
|
||||||
// Create Ethereum backend
|
// Create Ethereum backend
|
||||||
bc, err := core.NewBlockChain(chainDB, nil, genesis, nil, engine, vm.Config{}, nil)
|
bc, err := core.NewBlockChain(chainDB, genesis, engine, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("can't create new chain %v", err)
|
t.Fatalf("can't create new chain %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/txpool"
|
"github.com/ethereum/go-ethereum/core/txpool"
|
||||||
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
|
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -118,7 +117,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine
|
||||||
default:
|
default:
|
||||||
t.Fatalf("unexpected consensus engine type: %T", engine)
|
t.Fatalf("unexpected consensus engine type: %T", engine)
|
||||||
}
|
}
|
||||||
chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieDirtyDisabled: true}, gspec, nil, engine, vm.Config{}, nil)
|
chain, err := core.NewBlockChain(db, gspec, engine, &core.BlockChainConfig{ArchiveMode: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("core.NewBlockChain failed: %v", err)
|
t.Fatalf("core.NewBlockChain failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -151,15 +151,21 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *t
|
||||||
// Wrap the original engine within the beacon-engine
|
// Wrap the original engine within the beacon-engine
|
||||||
engine := beacon.New(ethash.NewFaker())
|
engine := beacon.New(ethash.NewFaker())
|
||||||
|
|
||||||
cache := &core.CacheConfig{TrieCleanLimit: 0, StateScheme: scheme, Preimages: true}
|
options := &core.BlockChainConfig{
|
||||||
if snapshotter {
|
TrieCleanLimit: 0,
|
||||||
cache.SnapshotLimit = 1
|
StateScheme: scheme,
|
||||||
cache.SnapshotWait = true
|
Preimages: true,
|
||||||
|
TxLookupLimit: -1, // disable tx indexing
|
||||||
|
VmConfig: vm.Config{
|
||||||
|
Tracer: tracer,
|
||||||
|
StatelessSelfValidation: witness,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
chain, err := core.NewBlockChain(db, cache, gspec, nil, engine, vm.Config{
|
if snapshotter {
|
||||||
Tracer: tracer,
|
options.SnapshotLimit = 1
|
||||||
StatelessSelfValidation: witness,
|
options.SnapshotWait = true
|
||||||
}, nil)
|
}
|
||||||
|
chain, err := core.NewBlockChain(db, gspec, engine, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,11 +64,10 @@ func NewSecure(stateRoot common.Hash, owner common.Hash, root common.Hash, db da
|
||||||
//
|
//
|
||||||
// StateTrie is not safe for concurrent use.
|
// StateTrie is not safe for concurrent use.
|
||||||
type StateTrie struct {
|
type StateTrie struct {
|
||||||
trie Trie
|
trie Trie
|
||||||
db database.NodeDatabase
|
db database.NodeDatabase
|
||||||
preimages preimageStore
|
preimages preimageStore
|
||||||
secKeyCache map[common.Hash][]byte
|
secKeyCache map[common.Hash][]byte
|
||||||
secKeyCacheOwner *StateTrie // Pointer to self, replace the key cache on mismatch
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStateTrie creates a trie with an existing root node from a backing database.
|
// NewStateTrie creates a trie with an existing root node from a backing database.
|
||||||
|
|
@ -84,7 +83,11 @@ func NewStateTrie(id *ID, db database.NodeDatabase) (*StateTrie, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tr := &StateTrie{trie: *trie, db: db}
|
tr := &StateTrie{
|
||||||
|
trie: *trie,
|
||||||
|
db: db,
|
||||||
|
secKeyCache: make(map[common.Hash][]byte),
|
||||||
|
}
|
||||||
|
|
||||||
// link the preimage store if it's supported
|
// link the preimage store if it's supported
|
||||||
if preimages, ok := db.(preimageStore); ok && preimages.PreimageEnabled() {
|
if preimages, ok := db.(preimageStore); ok && preimages.PreimageEnabled() {
|
||||||
|
|
@ -162,7 +165,7 @@ func (t *StateTrie) MustUpdate(key, value []byte) {
|
||||||
hk := crypto.Keccak256(key)
|
hk := crypto.Keccak256(key)
|
||||||
t.trie.MustUpdate(hk, value)
|
t.trie.MustUpdate(hk, value)
|
||||||
if t.preimages != nil {
|
if t.preimages != nil {
|
||||||
t.getSecKeyCache()[common.Hash(hk)] = common.CopyBytes(key)
|
t.secKeyCache[common.Hash(hk)] = common.CopyBytes(key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -182,7 +185,7 @@ func (t *StateTrie) UpdateStorage(_ common.Address, key, value []byte) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if t.preimages != nil {
|
if t.preimages != nil {
|
||||||
t.getSecKeyCache()[common.Hash(hk)] = common.CopyBytes(key)
|
t.secKeyCache[common.Hash(hk)] = common.CopyBytes(key)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -198,7 +201,7 @@ func (t *StateTrie) UpdateAccount(address common.Address, acc *types.StateAccoun
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if t.preimages != nil {
|
if t.preimages != nil {
|
||||||
t.getSecKeyCache()[common.Hash(hk)] = address.Bytes()
|
t.secKeyCache[common.Hash(hk)] = address.Bytes()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -212,7 +215,7 @@ func (t *StateTrie) UpdateContractCode(_ common.Address, _ common.Hash, _ []byte
|
||||||
func (t *StateTrie) MustDelete(key []byte) {
|
func (t *StateTrie) MustDelete(key []byte) {
|
||||||
hk := crypto.Keccak256(key)
|
hk := crypto.Keccak256(key)
|
||||||
if t.preimages != nil {
|
if t.preimages != nil {
|
||||||
delete(t.getSecKeyCache(), common.Hash(hk))
|
delete(t.secKeyCache, common.Hash(hk))
|
||||||
}
|
}
|
||||||
t.trie.MustDelete(hk)
|
t.trie.MustDelete(hk)
|
||||||
}
|
}
|
||||||
|
|
@ -223,7 +226,7 @@ func (t *StateTrie) MustDelete(key []byte) {
|
||||||
func (t *StateTrie) DeleteStorage(_ common.Address, key []byte) error {
|
func (t *StateTrie) DeleteStorage(_ common.Address, key []byte) error {
|
||||||
hk := crypto.Keccak256(key)
|
hk := crypto.Keccak256(key)
|
||||||
if t.preimages != nil {
|
if t.preimages != nil {
|
||||||
delete(t.getSecKeyCache(), common.Hash(hk))
|
delete(t.secKeyCache, common.Hash(hk))
|
||||||
}
|
}
|
||||||
return t.trie.Delete(hk)
|
return t.trie.Delete(hk)
|
||||||
}
|
}
|
||||||
|
|
@ -232,7 +235,7 @@ func (t *StateTrie) DeleteStorage(_ common.Address, key []byte) error {
|
||||||
func (t *StateTrie) DeleteAccount(address common.Address) error {
|
func (t *StateTrie) DeleteAccount(address common.Address) error {
|
||||||
hk := crypto.Keccak256(address.Bytes())
|
hk := crypto.Keccak256(address.Bytes())
|
||||||
if t.preimages != nil {
|
if t.preimages != nil {
|
||||||
delete(t.getSecKeyCache(), common.Hash(hk))
|
delete(t.secKeyCache, common.Hash(hk))
|
||||||
}
|
}
|
||||||
return t.trie.Delete(hk)
|
return t.trie.Delete(hk)
|
||||||
}
|
}
|
||||||
|
|
@ -243,7 +246,7 @@ func (t *StateTrie) GetKey(shaKey []byte) []byte {
|
||||||
if t.preimages == nil {
|
if t.preimages == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if key, ok := t.getSecKeyCache()[common.BytesToHash(shaKey)]; ok {
|
if key, ok := t.secKeyCache[common.BytesToHash(shaKey)]; ok {
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
return t.preimages.Preimage(common.BytesToHash(shaKey))
|
return t.preimages.Preimage(common.BytesToHash(shaKey))
|
||||||
|
|
@ -263,11 +266,11 @@ func (t *StateTrie) Witness() map[string]struct{} {
|
||||||
// be created with new root and updated trie database for following usage
|
// be created with new root and updated trie database for following usage
|
||||||
func (t *StateTrie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet) {
|
func (t *StateTrie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet) {
|
||||||
// Write all the pre-images to the actual disk database
|
// Write all the pre-images to the actual disk database
|
||||||
if len(t.getSecKeyCache()) > 0 {
|
if len(t.secKeyCache) > 0 {
|
||||||
if t.preimages != nil {
|
if t.preimages != nil {
|
||||||
t.preimages.InsertPreimage(t.secKeyCache)
|
t.preimages.InsertPreimage(t.secKeyCache)
|
||||||
}
|
}
|
||||||
t.secKeyCache = make(map[common.Hash][]byte)
|
clear(t.secKeyCache)
|
||||||
}
|
}
|
||||||
// Commit the trie and return its modified nodeset.
|
// Commit the trie and return its modified nodeset.
|
||||||
return t.trie.Commit(collectLeaf)
|
return t.trie.Commit(collectLeaf)
|
||||||
|
|
@ -284,7 +287,7 @@ func (t *StateTrie) Copy() *StateTrie {
|
||||||
return &StateTrie{
|
return &StateTrie{
|
||||||
trie: *t.trie.Copy(),
|
trie: *t.trie.Copy(),
|
||||||
db: t.db,
|
db: t.db,
|
||||||
secKeyCache: t.secKeyCache,
|
secKeyCache: make(map[common.Hash][]byte),
|
||||||
preimages: t.preimages,
|
preimages: t.preimages,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -301,17 +304,6 @@ func (t *StateTrie) MustNodeIterator(start []byte) NodeIterator {
|
||||||
return t.trie.MustNodeIterator(start)
|
return t.trie.MustNodeIterator(start)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getSecKeyCache returns the current secure key cache, creating a new one if
|
|
||||||
// ownership changed (i.e. the current secure trie is a copy of another owning
|
|
||||||
// the actual cache).
|
|
||||||
func (t *StateTrie) getSecKeyCache() map[common.Hash][]byte {
|
|
||||||
if t != t.secKeyCacheOwner {
|
|
||||||
t.secKeyCacheOwner = t
|
|
||||||
t.secKeyCache = make(map[common.Hash][]byte)
|
|
||||||
}
|
|
||||||
return t.secKeyCache
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *StateTrie) IsVerkle() bool {
|
func (t *StateTrie) IsVerkle() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -876,6 +876,7 @@ func (b *spongeBatch) Put(key, value []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (b *spongeBatch) Delete(key []byte) error { panic("implement me") }
|
func (b *spongeBatch) Delete(key []byte) error { panic("implement me") }
|
||||||
|
func (b *spongeBatch) DeleteRange(start, end []byte) error { panic("implement me") }
|
||||||
func (b *spongeBatch) ValueSize() int { return 100 }
|
func (b *spongeBatch) ValueSize() int { return 100 }
|
||||||
func (b *spongeBatch) Write() error { return nil }
|
func (b *spongeBatch) Write() error { return nil }
|
||||||
func (b *spongeBatch) Reset() {}
|
func (b *spongeBatch) Reset() {}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue