From 25fe3ba69a28781fa015460d8e53d589f8a6af47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Sat, 12 Aug 2023 05:07:36 +0200 Subject: [PATCH] feat: add startL1QueueIndex field to traces (#463) * feat: include startL1QueueIndex in traces * fix * update example --- core/block_validator.go | 2 +- core/trace.go | 44 ++++++++++++++++++++++++++++------- core/types/l2trace.go | 21 +++++++++-------- eth/tracers/api_blocktrace.go | 3 ++- miner/worker.go | 2 +- params/version.go | 2 +- 6 files changed, 51 insertions(+), 23 deletions(-) diff --git a/core/block_validator.go b/core/block_validator.go index 15af49741d..c7dfe8db0d 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -266,7 +266,7 @@ func (v *BlockValidator) createTraceEnv(block *types.Block) (*TraceEnv, error) { return nil, err } - return CreateTraceEnv(v.config, v.bc, v.engine, statedb, parent, block, true) + return CreateTraceEnv(v.config, v.bc, v.engine, v.db, statedb, parent, block, true) } func (v *BlockValidator) validateCircuitRowConsumption(block *types.Block) (*types.RowConsumption, error) { diff --git a/core/trace.go b/core/trace.go index 600403d7c2..9f6bdc899a 100644 --- a/core/trace.go +++ b/core/trace.go @@ -10,9 +10,11 @@ import ( "github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/common/hexutil" "github.com/scroll-tech/go-ethereum/consensus" + "github.com/scroll-tech/go-ethereum/core/rawdb" "github.com/scroll-tech/go-ethereum/core/state" "github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/core/vm" + "github.com/scroll-tech/go-ethereum/ethdb" "github.com/scroll-tech/go-ethereum/log" "github.com/scroll-tech/go-ethereum/params" "github.com/scroll-tech/go-ethereum/rollup/fees" @@ -44,6 +46,11 @@ type TraceEnv struct { // zktrie tracer is used for zktrie storage to build additional deletion proof ZkTrieTracer map[string]state.ZktrieProofTracer ExecutionResults []*types.ExecutionResult + + // StartL1QueueIndex is the next L1 message queue index that this block can process. + // Example: If the parent block included QueueIndex=9, then StartL1QueueIndex will + // be 10. + StartL1QueueIndex uint64 } // Context is the same as Context in eth/tracers/tracers.go @@ -59,7 +66,7 @@ type txTraceTask struct { index int } -func CreateTraceEnv(chainConfig *params.ChainConfig, chainContext ChainContext, engine consensus.Engine, statedb *state.StateDB, parent *types.Block, block *types.Block, commitAfterApply bool) (*TraceEnv, error) { +func CreateTraceEnv(chainConfig *params.ChainConfig, chainContext ChainContext, engine consensus.Engine, chaindb ethdb.Database, statedb *state.StateDB, parent *types.Block, block *types.Block, commitAfterApply bool) (*TraceEnv, error) { var coinbase common.Address var err error if chainConfig.Scroll.FeeVaultEnabled() { @@ -71,6 +78,23 @@ func CreateTraceEnv(chainConfig *params.ChainConfig, chainContext ChainContext, } } + // Collect start queue index, we should always have this value for blocks + // that have been executed. + // FIXME: This value will be incorrect on the signer, since we reuse this + // DB entry to signal which index the worker should continue from. + // Example: Ledger A <-- B <-- C. Block `A` contains up to `QueueIndex=9`. + // For block `B`, the worker skips 10 messages and includes 0. + // `ReadFirstQueueIndexNotInL2Block(B)` will then return `20` on the + // signer to avoid re-processing the same 10 transactions again for + // block `C`. + // `ReadFirstQueueIndexNotInL1Block(B)` will return the correct value + // `10` on follower nodes. + startL1QueueIndex := rawdb.ReadFirstQueueIndexNotInL2Block(chaindb, parent.Hash()) + if startL1QueueIndex == nil { + log.Error("missing FirstQueueIndexNotInL2Block for block during trace call", "number", parent.NumberU64(), "hash", parent.Hash()) + return nil, fmt.Errorf("missing FirstQueueIndexNotInL2Block for block during trace call: hash=%v, parentHash=%vv", block.Hash(), parent.Hash()) + } + env := &TraceEnv{ logConfig: &vm.LogConfig{ EnableMemory: false, @@ -88,9 +112,10 @@ func CreateTraceEnv(chainConfig *params.ChainConfig, chainContext ChainContext, Proofs: make(map[string][]hexutil.Bytes), StorageProofs: make(map[string]map[string][]hexutil.Bytes), }, - ZkTrieTracer: make(map[string]state.ZktrieProofTracer), - ExecutionResults: make([]*types.ExecutionResult, block.Transactions().Len()), - TxStorageTraces: make([]*types.StorageTrace, block.Transactions().Len()), + ZkTrieTracer: make(map[string]state.ZktrieProofTracer), + ExecutionResults: make([]*types.ExecutionResult, block.Transactions().Len()), + TxStorageTraces: make([]*types.StorageTrace, block.Transactions().Len()), + StartL1QueueIndex: *startL1QueueIndex, } key := coinbase.String() @@ -467,11 +492,12 @@ func (env *TraceEnv) fillBlockTrace(block *types.Block) (*types.BlockTrace, erro PoseidonCodeHash: statedb.GetPoseidonCodeHash(env.coinbase), CodeSize: statedb.GetCodeSize(env.coinbase), }, - Header: block.Header(), - StorageTrace: env.StorageTrace, - ExecutionResults: env.ExecutionResults, - TxStorageTraces: env.TxStorageTraces, - Transactions: txs, + Header: block.Header(), + StorageTrace: env.StorageTrace, + ExecutionResults: env.ExecutionResults, + TxStorageTraces: env.TxStorageTraces, + Transactions: txs, + StartL1QueueIndex: env.StartL1QueueIndex, } for i, tx := range block.Transactions() { diff --git a/core/types/l2trace.go b/core/types/l2trace.go index c60fd7b646..a4a8dd4843 100644 --- a/core/types/l2trace.go +++ b/core/types/l2trace.go @@ -11,16 +11,17 @@ import ( // BlockTrace contains block execution traces and results required for rollers. type BlockTrace struct { - ChainID uint64 `json:"chainID"` - Version string `json:"version"` - Coinbase *AccountWrapper `json:"coinbase"` - Header *Header `json:"header"` - Transactions []*TransactionData `json:"transactions"` - StorageTrace *StorageTrace `json:"storageTrace"` - TxStorageTraces []*StorageTrace `json:"txStorageTraces,omitempty"` - ExecutionResults []*ExecutionResult `json:"executionResults"` - MPTWitness *json.RawMessage `json:"mptwitness,omitempty"` - WithdrawTrieRoot common.Hash `json:"withdraw_trie_root,omitempty"` + ChainID uint64 `json:"chainID"` + Version string `json:"version"` + Coinbase *AccountWrapper `json:"coinbase"` + Header *Header `json:"header"` + Transactions []*TransactionData `json:"transactions"` + StorageTrace *StorageTrace `json:"storageTrace"` + TxStorageTraces []*StorageTrace `json:"txStorageTraces,omitempty"` + ExecutionResults []*ExecutionResult `json:"executionResults"` + MPTWitness *json.RawMessage `json:"mptwitness,omitempty"` + WithdrawTrieRoot common.Hash `json:"withdraw_trie_root,omitempty"` + StartL1QueueIndex uint64 `json:"startL1QueueIndex"` } // StorageTrace stores proofs of storage needed by storage circuit diff --git a/eth/tracers/api_blocktrace.go b/eth/tracers/api_blocktrace.go index 88dd6075c2..d257eb344e 100644 --- a/eth/tracers/api_blocktrace.go +++ b/eth/tracers/api_blocktrace.go @@ -65,5 +65,6 @@ func (api *API) createTraceEnv(ctx context.Context, config *TraceConfig, block * if err != nil { return nil, err } - return core.CreateTraceEnv(api.backend.ChainConfig(), api.chainContext(ctx), api.backend.Engine(), statedb, parent, block, true) + chaindb := api.backend.ChainDb() + return core.CreateTraceEnv(api.backend.ChainConfig(), api.chainContext(ctx), api.backend.Engine(), chaindb, statedb, parent, block, true) } diff --git a/miner/worker.go b/miner/worker.go index 6c5c9dfe67..57144697f7 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -763,7 +763,7 @@ func (w *worker) makeCurrent(parent *types.Block, header *types.Header) error { // don't commit the state during tracing for circuit capacity checker, otherwise we cannot revert. // and even if we don't commit the state, the `refund` value will still be correct, as explained in `CommitTransaction` commitStateAfterApply := false - traceEnv, err := core.CreateTraceEnv(w.chainConfig, w.chain, w.engine, state, parent, + traceEnv, err := core.CreateTraceEnv(w.chainConfig, w.chain, w.engine, w.eth.ChainDb(), state, parent, // new block with a placeholder tx, for traceEnv's ExecutionResults length & TxStorageTraces length types.NewBlockWithHeader(header).WithBody([]*types.Transaction{types.NewTx(&types.LegacyTx{})}, nil), commitStateAfterApply) diff --git a/params/version.go b/params/version.go index bb2b3bc910..046f866245 100644 --- a/params/version.go +++ b/params/version.go @@ -24,7 +24,7 @@ import ( const ( VersionMajor = 4 // Major version component of the current release VersionMinor = 3 // Minor version component of the current release - VersionPatch = 33 // Patch version component of the current release + VersionPatch = 34 // Patch version component of the current release VersionMeta = "sepolia" // Version metadata to append to the version string )