Skip to content

Commit b8ae093

Browse files
rjl493456442allformless
authored andcommitted
cmd, core, eth, tests: prevent state flushing in RPC (#33931)
Fixes ethereum/go-ethereum#33572
1 parent e38c766 commit b8ae093

6 files changed

Lines changed: 115 additions & 52 deletions

File tree

cmd/utils/flags.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2949,6 +2949,9 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
29492949
}
29502950
options.VmConfig = vmcfg
29512951

2952+
options.StatelessSelfValidation = ctx.Bool(VMStatelessSelfValidationFlag.Name) || ctx.Bool(VMWitnessStatsFlag.Name)
2953+
options.EnableWitnessStats = ctx.Bool(VMWitnessStatsFlag.Name)
2954+
29522955
chain, err := core.NewBlockChain(chainDb, gspec, engine, options)
29532956
if err != nil {
29542957
Fatalf("Can't create BlockChain: %v", err)

core/blockchain.go

Lines changed: 84 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package core
1919

2020
import (
21+
"context"
2122
"errors"
2223
"fmt"
2324
"io"
@@ -233,6 +234,15 @@ type BlockChainConfig struct {
233234

234235
// EnableBAL enables the block access list feature
235236
EnableBAL bool
237+
238+
// SlowBlockThreshold is the block execution time threshold beyond which
239+
// detailed statistics will be logged. Negative value means disabled (default),
240+
// zero logs all blocks, positive value filters blocks by execution time.
241+
SlowBlockThreshold time.Duration
242+
243+
// Execution configs
244+
StatelessSelfValidation bool // Generate execution witnesses and self-check against them (testing purpose)
245+
EnableWitnessStats bool // Whether trie access statistics collection is enabled
236246
}
237247

238248
// DefaultConfig returns the default config.
@@ -2404,7 +2414,15 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
24042414
bc.updateHighestVerifiedHeader(block.Header())
24052415
// The traced section of block import.
24062416
start := time.Now()
2407-
res, err := bc.ProcessBlock(parent.Root, block, setHead, makeWitness && len(chain) == 1)
2417+
config := ExecuteConfig{
2418+
WriteState: true,
2419+
WriteHead: setHead,
2420+
EnableTracer: true,
2421+
MakeWitness: makeWitness && len(chain) == 1,
2422+
StatelessSelfValidation: bc.cfg.StatelessSelfValidation,
2423+
EnableWitnessStats: bc.cfg.EnableWitnessStats,
2424+
}
2425+
res, err := bc.ProcessBlock(context.Background(), parent.Root, block, config)
24082426
if err != nil {
24092427
return nil, it.index, err
24102428
}
@@ -2507,9 +2525,36 @@ func (bpr *blockProcessingResult) Witness() *stateless.Witness {
25072525
return bpr.witness
25082526
}
25092527

2528+
// ExecuteConfig defines optional behaviors during execution.
2529+
type ExecuteConfig struct {
2530+
// WriteState controls whether the computed state changes are persisted to
2531+
// the underlying storage. If false, execution is performed in-memory only.
2532+
WriteState bool
2533+
2534+
// WriteHead indicates whether the execution result should update the canonical
2535+
// chain head. It's only relevant with WriteState == True.
2536+
WriteHead bool
2537+
2538+
// EnableTracer enables execution tracing. This is typically used for debugging
2539+
// or analysis and may significantly impact performance.
2540+
EnableTracer bool
2541+
2542+
// MakeWitness indicates whether to generate execution witness data during
2543+
// execution. Enabling this may introduce additional memory and CPU overhead.
2544+
MakeWitness bool
2545+
2546+
// StatelessSelfValidation indicates whether the execution witnesses generation
2547+
// and self-validation (testing purpose) is enabled.
2548+
StatelessSelfValidation bool
2549+
2550+
// EnableWitnessStats indicates whether to enable collection of witness trie
2551+
// access statistics
2552+
EnableWitnessStats bool
2553+
}
2554+
25102555
// ProcessBlock executes and validates the given block. If there was no error
25112556
// it writes the block and associated state to database.
2512-
func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, setHead bool, makeWitness bool) (_ *blockProcessingResult, blockEndErr error) {
2557+
func (bc *BlockChain) ProcessBlock(ctx context.Context, parentRoot common.Hash, block *types.Block, config ExecuteConfig) (result *blockProcessingResult, blockEndErr error) {
25132558
var (
25142559
err error
25152560
startTime = time.Now()
@@ -2587,32 +2632,35 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
25872632
// Generate witnesses either if we're self-testing, or if it's the
25882633
// only block being inserted. A bit crude, but witnesses are huge,
25892634
// so we refuse to make an entire chain of them.
2590-
if bc.cfg.VmConfig.StatelessSelfValidation || makeWitness {
2635+
if config.StatelessSelfValidation || config.MakeWitness {
25912636
witness, err = stateless.NewWitness(block.Header(), bc)
25922637
if err != nil {
25932638
return nil, err
25942639
}
2595-
if bc.cfg.VmConfig.EnableWitnessStats {
2640+
if config.EnableWitnessStats {
25962641
witnessStats = stateless.NewWitnessStats()
25972642
}
25982643
}
25992644
statedb.StartPrefetcher("chain", witness, witnessStats)
26002645
defer statedb.StopPrefetcher()
26012646
}
26022647

2603-
if bc.logger != nil && bc.logger.OnBlockStart != nil {
2604-
td := bc.GetTd(block.ParentHash(), block.NumberU64()-1)
2605-
bc.logger.OnBlockStart(tracing.BlockEvent{
2606-
Block: block,
2607-
TD: td,
2608-
Finalized: bc.CurrentFinalBlock(),
2609-
Safe: bc.CurrentSafeBlock(),
2610-
})
2611-
}
2612-
if bc.logger != nil && bc.logger.OnBlockEnd != nil {
2613-
defer func() {
2614-
bc.logger.OnBlockEnd(blockEndErr)
2615-
}()
2648+
// Instrument the blockchain tracing
2649+
if config.EnableTracer {
2650+
if bc.logger != nil && bc.logger.OnBlockStart != nil {
2651+
td := bc.GetTd(block.ParentHash(), block.NumberU64()-1)
2652+
bc.logger.OnBlockStart(tracing.BlockEvent{
2653+
Block: block,
2654+
TD: td,
2655+
Finalized: bc.CurrentFinalBlock(),
2656+
Safe: bc.CurrentSafeBlock(),
2657+
})
2658+
}
2659+
if bc.logger != nil && bc.logger.OnBlockEnd != nil {
2660+
defer func() {
2661+
bc.logger.OnBlockEnd(blockEndErr)
2662+
}()
2663+
}
26162664
}
26172665

26182666
// Process block using the parent state as reference point
@@ -2640,7 +2688,7 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
26402688
// witness builder/runner, which would otherwise be impossible due to the
26412689
// various invalid chain states/behaviors being contained in those tests.
26422690
xvstart := time.Now()
2643-
if witness := statedb.Witness(); witness != nil && bc.cfg.VmConfig.StatelessSelfValidation {
2691+
if witness := statedb.Witness(); witness != nil && config.StatelessSelfValidation {
26442692
log.Warn("Running stateless self-validation", "block", block.Number(), "hash", block.Hash())
26452693

26462694
// Remove critical computed fields from the block to force true recalculation
@@ -2685,30 +2733,29 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
26852733
blockCrossValidationTimer.Update(xvtime) // The time spent on stateless cross validation
26862734

26872735
// Write the block to the chain and get the status.
2688-
var (
2689-
wstart = time.Now()
2690-
status WriteStatus
2691-
)
2692-
if !setHead {
2693-
// Don't set the head, only insert the block
2694-
err = bc.writeBlockWithState(block, res.Receipts, statedb)
2695-
} else {
2696-
status, err = bc.writeBlockAndSetHead(block, res.Receipts, res.Logs, statedb, nil)
2697-
}
2698-
if err != nil {
2699-
return nil, err
2736+
var status WriteStatus
2737+
if config.WriteState {
2738+
wstart := time.Now()
2739+
if !config.WriteHead {
2740+
// Don't set the head, only insert the block
2741+
err = bc.writeBlockWithState(block, res.Receipts, statedb)
2742+
} else {
2743+
status, err = bc.writeBlockAndSetHead(block, res.Receipts, res.Logs, statedb, nil)
2744+
}
2745+
if err != nil {
2746+
return nil, err
2747+
}
2748+
// Update the metrics touched during block commit
2749+
accountCommitTimer.Update(statedb.AccountCommits)
2750+
storageCommitTimer.Update(statedb.StorageCommits)
2751+
snapshotCommitTimer.Update(statedb.SnapshotCommits)
2752+
triedbCommitTimer.Update(statedb.TrieDBCommits)
2753+
blockWriteTimer.Update(time.Since(wstart) - max(statedb.AccountCommits, statedb.StorageCommits) /* concurrent */ - statedb.SnapshotCommits - statedb.TrieDBCommits)
27002754
}
27012755
// Report the collected witness statistics
27022756
if witnessStats != nil {
27032757
witnessStats.ReportMetrics(block.NumberU64())
27042758
}
2705-
2706-
// Update the metrics touched during block commit
2707-
accountCommitTimer.Update(statedb.AccountCommits) // Account commits are complete, we can mark them
2708-
storageCommitTimer.Update(statedb.StorageCommits) // Storage commits are complete, we can mark them
2709-
snapshotCommitTimer.Update(statedb.SnapshotCommits) // Snapshot commits are complete, we can mark them
2710-
triedbCommitTimer.Update(statedb.TrieDBCommits) // Trie database commits are complete, we can mark them
2711-
blockWriteTimer.Update(time.Since(wstart) - max(statedb.AccountCommits, statedb.StorageCommits) /* concurrent */ - statedb.SnapshotCommits - statedb.TrieDBCommits)
27122759
elapsed := time.Since(startTime) + 1 // prevent zero division
27132760
blockInsertTimer.Update(elapsed)
27142761
blockInsertTxSizeGauge.Update(int64(len(block.Transactions())))

eth/api_debug.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
"github.com/ethereum/go-ethereum/common"
2626
"github.com/ethereum/go-ethereum/common/hexutil"
27+
"github.com/ethereum/go-ethereum/core"
2728
"github.com/ethereum/go-ethereum/core/rawdb"
2829
"github.com/ethereum/go-ethereum/core/state"
2930
"github.com/ethereum/go-ethereum/core/stateless"
@@ -496,19 +497,23 @@ func (api *DebugAPI) StateSize(blockHashOrNumber *rpc.BlockNumberOrHash) (interf
496497
}, nil
497498
}
498499

499-
func (api *DebugAPI) ExecutionWitness(bn rpc.BlockNumber) (*stateless.ExtWitness, error) {
500+
func (api *DebugAPI) ExecutionWitness(bn rpc.BlockNumberOrHash) (*stateless.ExtWitness, error) {
500501
bc := api.eth.blockchain
501-
block, err := api.eth.APIBackend.BlockByNumber(context.Background(), bn)
502+
block, err := api.eth.APIBackend.BlockByNumberOrHash(context.Background(), bn)
502503
if err != nil {
503-
return &stateless.ExtWitness{}, fmt.Errorf("block number %v not found", bn)
504+
return &stateless.ExtWitness{}, fmt.Errorf("block %v not found", bn)
504505
}
505506

506507
parent := bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
507508
if parent == nil {
508-
return &stateless.ExtWitness{}, fmt.Errorf("block number %v found, but parent missing", bn)
509+
return &stateless.ExtWitness{}, fmt.Errorf("block %v found, but parent missing", bn)
509510
}
510-
511-
result, err := bc.ProcessBlock(parent.Root, block, false, true)
511+
config := core.ExecuteConfig{
512+
WriteState: false,
513+
EnableTracer: false,
514+
MakeWitness: true,
515+
}
516+
result, err := bc.ProcessBlock(context.Background(), parent.Root, block, config)
512517
if err != nil {
513518
return nil, err
514519
}
@@ -527,8 +532,12 @@ func (api *DebugAPI) ExecutionWitnessByHash(hash common.Hash) (*stateless.ExtWit
527532
if parent == nil {
528533
return &stateless.ExtWitness{}, fmt.Errorf("block number %x found, but parent missing", hash)
529534
}
530-
531-
result, err := bc.ProcessBlock(parent.Root, block, false, true)
535+
config := core.ExecuteConfig{
536+
WriteState: false,
537+
EnableTracer: false,
538+
MakeWitness: true,
539+
}
540+
result, err := bc.ProcessBlock(context.Background(), parent.Root, block, config)
532541
if err != nil {
533542
return nil, err
534543
}

eth/backend.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,9 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
371371
// - DATADIR/triedb/verkle.journal
372372
TrieJournalDirectory: stack.ResolvePath("triedb"),
373373
StateSizeTracking: config.EnableStateSizeTracking,
374+
375+
StatelessSelfValidation: config.StatelessSelfValidation,
376+
EnableWitnessStats: config.EnableWitnessStats,
374377
}
375378
)
376379
if config.DisableTxIndexer {

internal/web3ext/web3ext.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -413,11 +413,6 @@ web3._extend({
413413
params: 2,
414414
inputFormatter:[null, null],
415415
}),
416-
new web3._extend.Method({
417-
name: 'freezeClient',
418-
call: 'debug_freezeClient',
419-
params: 1,
420-
}),
421416
new web3._extend.Method({
422417
name: 'getAccessibleState',
423418
call: 'debug_getAccessibleState',
@@ -460,6 +455,12 @@ web3._extend({
460455
params: 1,
461456
inputFormatter: [null],
462457
}),
458+
new web3._extend.Method({
459+
name: 'executionWitness',
460+
call: 'debug_executionWitness',
461+
params: 1,
462+
inputFormatter: [null],
463+
}),
463464
],
464465
properties: []
465466
});

tests/block_test_util.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,9 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *t
158158
Preimages: true,
159159
TxLookupLimit: -1, // disable tx indexing
160160
VmConfig: vm.Config{
161-
Tracer: tracer,
162-
StatelessSelfValidation: witness,
161+
Tracer: tracer,
163162
},
163+
StatelessSelfValidation: witness,
164164
}
165165
if snapshotter {
166166
options.SnapshotLimit = 1

0 commit comments

Comments
 (0)