feat: add startL1QueueIndex field to traces (#463)

* feat: include startL1QueueIndex in traces

* fix

* update example
This commit is contained in:
Péter Garamvölgyi 2023-08-12 05:07:36 +02:00 committed by GitHub
parent cb38ec47a5
commit 25fe3ba69a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 51 additions and 23 deletions

View file

@ -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) {

View file

@ -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() {

View file

@ -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

View file

@ -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)
}

View file

@ -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)

View file

@ -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
)