mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 14:46:42 +00:00
feat(api/rawdb): allow storing traces for skipped txs (#500)
This commit is contained in:
parent
2d9d48d463
commit
0b6c3be40d
10 changed files with 132 additions and 29 deletions
|
|
@ -130,6 +130,7 @@ var (
|
||||||
utils.MinerExtraDataFlag,
|
utils.MinerExtraDataFlag,
|
||||||
utils.MinerRecommitIntervalFlag,
|
utils.MinerRecommitIntervalFlag,
|
||||||
utils.MinerNoVerifyFlag,
|
utils.MinerNoVerifyFlag,
|
||||||
|
utils.MinerStoreSkippedTxTracesFlag,
|
||||||
utils.NATFlag,
|
utils.NATFlag,
|
||||||
utils.NoDiscoverFlag,
|
utils.NoDiscoverFlag,
|
||||||
utils.DiscoveryV5Flag,
|
utils.DiscoveryV5Flag,
|
||||||
|
|
|
||||||
|
|
@ -192,6 +192,7 @@ var AppHelpFlagGroups = []flags.FlagGroup{
|
||||||
utils.MinerExtraDataFlag,
|
utils.MinerExtraDataFlag,
|
||||||
utils.MinerRecommitIntervalFlag,
|
utils.MinerRecommitIntervalFlag,
|
||||||
utils.MinerNoVerifyFlag,
|
utils.MinerNoVerifyFlag,
|
||||||
|
utils.MinerStoreSkippedTxTracesFlag,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -491,6 +491,10 @@ var (
|
||||||
Name: "miner.noverify",
|
Name: "miner.noverify",
|
||||||
Usage: "Disable remote sealing verification",
|
Usage: "Disable remote sealing verification",
|
||||||
}
|
}
|
||||||
|
MinerStoreSkippedTxTracesFlag = cli.BoolFlag{
|
||||||
|
Name: "miner.storeskippedtxtraces",
|
||||||
|
Usage: "Store the wrapped traces when storing a skipped tx",
|
||||||
|
}
|
||||||
// Account settings
|
// Account settings
|
||||||
UnlockedAccountFlag = cli.StringFlag{
|
UnlockedAccountFlag = cli.StringFlag{
|
||||||
Name: "unlock",
|
Name: "unlock",
|
||||||
|
|
@ -1488,6 +1492,9 @@ func setMiner(ctx *cli.Context, cfg *miner.Config) {
|
||||||
if ctx.GlobalIsSet(MinerNoVerifyFlag.Name) {
|
if ctx.GlobalIsSet(MinerNoVerifyFlag.Name) {
|
||||||
cfg.Noverify = ctx.GlobalBool(MinerNoVerifyFlag.Name)
|
cfg.Noverify = ctx.GlobalBool(MinerNoVerifyFlag.Name)
|
||||||
}
|
}
|
||||||
|
if ctx.GlobalIsSet(MinerStoreSkippedTxTracesFlag.Name) {
|
||||||
|
cfg.StoreSkippedTxTraces = ctx.GlobalBool(MinerStoreSkippedTxTracesFlag.Name)
|
||||||
|
}
|
||||||
if ctx.GlobalIsSet(LegacyMinerGasTargetFlag.Name) {
|
if ctx.GlobalIsSet(LegacyMinerGasTargetFlag.Name) {
|
||||||
log.Warn("The generic --miner.gastarget flag is deprecated and will be removed in the future!")
|
log.Warn("The generic --miner.gastarget flag is deprecated and will be removed in the future!")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -179,7 +179,7 @@ func (v *BlockValidator) ValidateL1Messages(block *types.Block) error {
|
||||||
l1msg := it.L1Message()
|
l1msg := it.L1Message()
|
||||||
skippedTx := types.NewTx(&l1msg)
|
skippedTx := types.NewTx(&l1msg)
|
||||||
log.Debug("Skipped L1 message", "queueIndex", index, "tx", skippedTx.Hash().String(), "block", blockHash.String())
|
log.Debug("Skipped L1 message", "queueIndex", index, "tx", skippedTx.Hash().String(), "block", blockHash.String())
|
||||||
rawdb.WriteSkippedTransaction(v.db, skippedTx, "unknown", block.NumberU64(), &blockHash)
|
rawdb.WriteSkippedTransaction(v.db, skippedTx, nil, "unknown", block.NumberU64(), &blockHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
queueIndex = txQueueIndex + 1
|
queueIndex = txQueueIndex + 1
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package rawdb
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"encoding/json"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
|
@ -61,8 +62,50 @@ type SkippedTransaction struct {
|
||||||
BlockHash *common.Hash
|
BlockHash *common.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SkippedTransactionV2 stores the SkippedTransaction object along with serialized traces.
|
||||||
|
type SkippedTransactionV2 struct {
|
||||||
|
// Tx is the skipped transaction.
|
||||||
|
// We store the tx itself otherwise geth will discard it after skipping.
|
||||||
|
Tx *types.Transaction
|
||||||
|
|
||||||
|
// Traces is the serialized wrapped traces of the skipped transaction.
|
||||||
|
// We only store it when `MinerStoreSkippedTxTracesFlag` is enabled, so it might be empty.
|
||||||
|
// Note that we do not directly utilize `*types.BlockTrace` due to the fact that
|
||||||
|
// types.BlockTrace.StorageTrace.Proofs is of type `map[string][]hexutil.Bytes`, which is not RLP-serializable.
|
||||||
|
TracesBytes []byte
|
||||||
|
|
||||||
|
// Reason is the skip reason.
|
||||||
|
Reason string
|
||||||
|
|
||||||
|
// BlockNumber is the number of the block in which this transaction was skipped.
|
||||||
|
BlockNumber uint64
|
||||||
|
|
||||||
|
// BlockNumber is the hash of the block in which this transaction was skipped or nil.
|
||||||
|
BlockHash *common.Hash
|
||||||
|
}
|
||||||
|
|
||||||
// writeSkippedTransaction writes a skipped transaction to the database.
|
// writeSkippedTransaction writes a skipped transaction to the database.
|
||||||
func writeSkippedTransaction(db ethdb.KeyValueWriter, tx *types.Transaction, reason string, blockNumber uint64, blockHash *common.Hash) {
|
func writeSkippedTransaction(db ethdb.KeyValueWriter, tx *types.Transaction, traces *types.BlockTrace, reason string, blockNumber uint64, blockHash *common.Hash) {
|
||||||
|
// workaround: RLP decoding fails if this is nil
|
||||||
|
if blockHash == nil {
|
||||||
|
blockHash = &common.Hash{}
|
||||||
|
}
|
||||||
|
b, err := json.Marshal(traces)
|
||||||
|
if err != nil {
|
||||||
|
log.Crit("Failed to json marshal skipped transaction", "hash", tx.Hash().String(), "err", err)
|
||||||
|
}
|
||||||
|
stx := SkippedTransactionV2{Tx: tx, TracesBytes: b, Reason: reason, BlockNumber: blockNumber, BlockHash: blockHash}
|
||||||
|
bytes, err := rlp.EncodeToBytes(stx)
|
||||||
|
if err != nil {
|
||||||
|
log.Crit("Failed to RLP encode skipped transaction", "hash", tx.Hash().String(), "err", err)
|
||||||
|
}
|
||||||
|
if err := db.Put(SkippedTransactionKey(tx.Hash()), bytes); err != nil {
|
||||||
|
log.Crit("Failed to store skipped transaction", "hash", tx.Hash().String(), "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeSkippedTransactionV1 is the old version of writeSkippedTransaction, we keep it for testing compatibility purpose.
|
||||||
|
func writeSkippedTransactionV1(db ethdb.KeyValueWriter, tx *types.Transaction, reason string, blockNumber uint64, blockHash *common.Hash) {
|
||||||
// workaround: RLP decoding fails if this is nil
|
// workaround: RLP decoding fails if this is nil
|
||||||
if blockHash == nil {
|
if blockHash == nil {
|
||||||
blockHash = &common.Hash{}
|
blockHash = &common.Hash{}
|
||||||
|
|
@ -70,7 +113,7 @@ func writeSkippedTransaction(db ethdb.KeyValueWriter, tx *types.Transaction, rea
|
||||||
stx := SkippedTransaction{Tx: tx, Reason: reason, BlockNumber: blockNumber, BlockHash: blockHash}
|
stx := SkippedTransaction{Tx: tx, Reason: reason, BlockNumber: blockNumber, BlockHash: blockHash}
|
||||||
bytes, err := rlp.EncodeToBytes(stx)
|
bytes, err := rlp.EncodeToBytes(stx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Crit("Failed to RLP encode skipped transaction", "err", err)
|
log.Crit("Failed to RLP encode skipped transaction", "hash", tx.Hash().String(), "err", err)
|
||||||
}
|
}
|
||||||
if err := db.Put(SkippedTransactionKey(tx.Hash()), bytes); err != nil {
|
if err := db.Put(SkippedTransactionKey(tx.Hash()), bytes); err != nil {
|
||||||
log.Crit("Failed to store skipped transaction", "hash", tx.Hash().String(), "err", err)
|
log.Crit("Failed to store skipped transaction", "hash", tx.Hash().String(), "err", err)
|
||||||
|
|
@ -90,19 +133,27 @@ func readSkippedTransactionRLP(db ethdb.Reader, txHash common.Hash) rlp.RawValue
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadSkippedTransaction retrieves a skipped transaction by its hash, along with its skipped reason.
|
// ReadSkippedTransaction retrieves a skipped transaction by its hash, along with its skipped reason.
|
||||||
func ReadSkippedTransaction(db ethdb.Reader, txHash common.Hash) *SkippedTransaction {
|
func ReadSkippedTransaction(db ethdb.Reader, txHash common.Hash) *SkippedTransactionV2 {
|
||||||
data := readSkippedTransactionRLP(db, txHash)
|
data := readSkippedTransactionRLP(db, txHash)
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
var stxV2 SkippedTransactionV2
|
||||||
var stx SkippedTransaction
|
var stx SkippedTransaction
|
||||||
|
if err := rlp.Decode(bytes.NewReader(data), &stxV2); err != nil {
|
||||||
if err := rlp.Decode(bytes.NewReader(data), &stx); err != nil {
|
if err := rlp.Decode(bytes.NewReader(data), &stx); err != nil {
|
||||||
log.Crit("Invalid skipped transaction RLP", "hash", txHash.String(), "data", data, "err", err)
|
log.Crit("Invalid skipped transaction RLP", "hash", txHash.String(), "data", data, "err", err)
|
||||||
}
|
}
|
||||||
if stx.BlockHash != nil && *stx.BlockHash == (common.Hash{}) {
|
stxV2.Tx = stx.Tx
|
||||||
stx.BlockHash = nil
|
stxV2.Reason = stx.Reason
|
||||||
|
stxV2.BlockNumber = stx.BlockNumber
|
||||||
|
stxV2.BlockHash = stx.BlockHash
|
||||||
}
|
}
|
||||||
return &stx
|
|
||||||
|
if stxV2.BlockHash != nil && *stxV2.BlockHash == (common.Hash{}) {
|
||||||
|
stxV2.BlockHash = nil
|
||||||
|
}
|
||||||
|
return &stxV2
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeSkippedTransactionHash writes the hash of a skipped transaction to the database.
|
// writeSkippedTransactionHash writes the hash of a skipped transaction to the database.
|
||||||
|
|
@ -127,7 +178,7 @@ func ReadSkippedTransactionHash(db ethdb.Reader, index uint64) *common.Hash {
|
||||||
|
|
||||||
// WriteSkippedTransaction writes a skipped transaction to the database and also updates the count and lookup index.
|
// WriteSkippedTransaction writes a skipped transaction to the database and also updates the count and lookup index.
|
||||||
// Note: The lookup index and count will include duplicates if there are chain reorgs.
|
// Note: The lookup index and count will include duplicates if there are chain reorgs.
|
||||||
func WriteSkippedTransaction(db ethdb.Database, tx *types.Transaction, reason string, blockNumber uint64, blockHash *common.Hash) {
|
func WriteSkippedTransaction(db ethdb.Database, tx *types.Transaction, traces *types.BlockTrace, reason string, blockNumber uint64, blockHash *common.Hash) {
|
||||||
// this method is not accessed concurrently, but just to be sure...
|
// this method is not accessed concurrently, but just to be sure...
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
defer mu.Unlock()
|
defer mu.Unlock()
|
||||||
|
|
@ -136,7 +187,7 @@ func WriteSkippedTransaction(db ethdb.Database, tx *types.Transaction, reason st
|
||||||
|
|
||||||
// update in a batch
|
// update in a batch
|
||||||
batch := db.NewBatch()
|
batch := db.NewBatch()
|
||||||
writeSkippedTransaction(db, tx, reason, blockNumber, blockHash)
|
writeSkippedTransaction(db, tx, traces, reason, blockNumber, blockHash)
|
||||||
writeSkippedTransactionHash(db, index, tx.Hash())
|
writeSkippedTransactionHash(db, index, tx.Hash())
|
||||||
writeNumSkippedTransactions(db, index+1)
|
writeNumSkippedTransactions(db, index+1)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,17 @@ func newTestTransaction(queueIndex uint64) *types.Transaction {
|
||||||
func TestReadWriteSkippedTransactionNoIndex(t *testing.T) {
|
func TestReadWriteSkippedTransactionNoIndex(t *testing.T) {
|
||||||
tx := newTestTransaction(123)
|
tx := newTestTransaction(123)
|
||||||
db := NewMemoryDatabase()
|
db := NewMemoryDatabase()
|
||||||
writeSkippedTransaction(db, tx, "random reason", 1, &common.Hash{1})
|
writeSkippedTransaction(db, tx, nil, "random reason", 1, &common.Hash{1})
|
||||||
|
got := ReadSkippedTransaction(db, tx.Hash())
|
||||||
|
if got == nil || got.Tx.Hash() != tx.Hash() || got.Reason != "random reason" || got.BlockNumber != 1 || got.BlockHash == nil || *got.BlockHash != (common.Hash{1}) {
|
||||||
|
t.Fatal("Skipped transaction mismatch", "got", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReadSkippedTransactionV1AsV2(t *testing.T) {
|
||||||
|
tx := newTestTransaction(123)
|
||||||
|
db := NewMemoryDatabase()
|
||||||
|
writeSkippedTransactionV1(db, tx, "random reason", 1, &common.Hash{1})
|
||||||
got := ReadSkippedTransaction(db, tx.Hash())
|
got := ReadSkippedTransaction(db, tx.Hash())
|
||||||
if got == nil || got.Tx.Hash() != tx.Hash() || got.Reason != "random reason" || got.BlockNumber != 1 || got.BlockHash == nil || *got.BlockHash != (common.Hash{1}) {
|
if got == nil || got.Tx.Hash() != tx.Hash() || got.Reason != "random reason" || got.BlockNumber != 1 || got.BlockHash == nil || *got.BlockHash != (common.Hash{1}) {
|
||||||
t.Fatal("Skipped transaction mismatch", "got", got)
|
t.Fatal("Skipped transaction mismatch", "got", got)
|
||||||
|
|
@ -54,7 +64,7 @@ func TestReadWriteSkippedTransactionNoIndex(t *testing.T) {
|
||||||
func TestReadWriteSkippedTransaction(t *testing.T) {
|
func TestReadWriteSkippedTransaction(t *testing.T) {
|
||||||
tx := newTestTransaction(123)
|
tx := newTestTransaction(123)
|
||||||
db := NewMemoryDatabase()
|
db := NewMemoryDatabase()
|
||||||
WriteSkippedTransaction(db, tx, "random reason", 1, &common.Hash{1})
|
WriteSkippedTransaction(db, tx, nil, "random reason", 1, &common.Hash{1})
|
||||||
got := ReadSkippedTransaction(db, tx.Hash())
|
got := ReadSkippedTransaction(db, tx.Hash())
|
||||||
if got == nil || got.Tx.Hash() != tx.Hash() || got.Reason != "random reason" || got.BlockNumber != 1 || got.BlockHash == nil || *got.BlockHash != (common.Hash{1}) {
|
if got == nil || got.Tx.Hash() != tx.Hash() || got.Reason != "random reason" || got.BlockNumber != 1 || got.BlockHash == nil || *got.BlockHash != (common.Hash{1}) {
|
||||||
t.Fatal("Skipped transaction mismatch", "got", got)
|
t.Fatal("Skipped transaction mismatch", "got", got)
|
||||||
|
|
@ -78,7 +88,7 @@ func TestSkippedTransactionConcurrentUpdate(t *testing.T) {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
WriteSkippedTransaction(db, tx, "random reason", 1, &common.Hash{1})
|
WriteSkippedTransaction(db, tx, nil, "random reason", 1, &common.Hash{1})
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
@ -100,12 +110,12 @@ func TestIterateSkippedTransactions(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
WriteSkippedTransaction(db, tx, "random reason", 1, &common.Hash{1})
|
WriteSkippedTransaction(db, tx, nil, "random reason", 1, &common.Hash{1})
|
||||||
}
|
}
|
||||||
|
|
||||||
// simulate skipped L2 tx that's not included in the index
|
// simulate skipped L2 tx that's not included in the index
|
||||||
l2tx := newTestTransaction(6)
|
l2tx := newTestTransaction(6)
|
||||||
writeSkippedTransaction(db, l2tx, "random reason", 1, &common.Hash{1})
|
writeSkippedTransaction(db, l2tx, nil, "random reason", 1, &common.Hash{1})
|
||||||
|
|
||||||
it := IterateSkippedTransactionsFrom(db, 2)
|
it := IterateSkippedTransactionsFrom(db, 2)
|
||||||
defer it.Release()
|
defer it.Release()
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ package eth
|
||||||
import (
|
import (
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
@ -720,6 +721,9 @@ type RPCTransaction struct {
|
||||||
SkipReason string `json:"skipReason"`
|
SkipReason string `json:"skipReason"`
|
||||||
SkipBlockNumber *hexutil.Big `json:"skipBlockNumber"`
|
SkipBlockNumber *hexutil.Big `json:"skipBlockNumber"`
|
||||||
SkipBlockHash *common.Hash `json:"skipBlockHash,omitempty"`
|
SkipBlockHash *common.Hash `json:"skipBlockHash,omitempty"`
|
||||||
|
|
||||||
|
// wrapped traces, currently only available for `scroll_getSkippedTransaction` API, when `MinerStoreSkippedTxTracesFlag` is set
|
||||||
|
Traces *types.BlockTrace `json:"traces,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSkippedTransaction returns a skipped transaction by its hash.
|
// GetSkippedTransaction returns a skipped transaction by its hash.
|
||||||
|
|
@ -733,6 +737,11 @@ func (api *ScrollAPI) GetSkippedTransaction(ctx context.Context, hash common.Has
|
||||||
rpcTx.SkipReason = stx.Reason
|
rpcTx.SkipReason = stx.Reason
|
||||||
rpcTx.SkipBlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(stx.BlockNumber))
|
rpcTx.SkipBlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(stx.BlockNumber))
|
||||||
rpcTx.SkipBlockHash = stx.BlockHash
|
rpcTx.SkipBlockHash = stx.BlockHash
|
||||||
|
if len(stx.TracesBytes) != 0 {
|
||||||
|
if err := json.Unmarshal(stx.TracesBytes, rpcTx.Traces); err != nil {
|
||||||
|
return nil, fmt.Errorf("fail to Unmarshal traces for skipped tx, hash: %s, err: %w", hash.String(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
return &rpcTx, nil
|
return &rpcTx, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,8 @@ type Config struct {
|
||||||
GasPrice *big.Int // Minimum gas price for mining a transaction
|
GasPrice *big.Int // Minimum gas price for mining a transaction
|
||||||
Recommit time.Duration // The time interval for miner to re-create mining work.
|
Recommit time.Duration // The time interval for miner to re-create mining work.
|
||||||
Noverify bool // Disable remote mining solution verification(only useful in ethash).
|
Noverify bool // Disable remote mining solution verification(only useful in ethash).
|
||||||
|
|
||||||
|
StoreSkippedTxTraces bool // Whether store the wrapped traces when storing a skipped tx
|
||||||
}
|
}
|
||||||
|
|
||||||
// Miner creates blocks and searches for proof-of-work values.
|
// Miner creates blocks and searches for proof-of-work values.
|
||||||
|
|
|
||||||
|
|
@ -884,8 +884,10 @@ func (w *worker) updateSnapshot() {
|
||||||
w.snapshotState = w.current.state.Copy()
|
w.snapshotState = w.current.state.Copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) commitTransaction(tx *types.Transaction, coinbase common.Address) ([]*types.Log, error) {
|
func (w *worker) commitTransaction(tx *types.Transaction, coinbase common.Address) ([]*types.Log, *types.BlockTrace, error) {
|
||||||
var accRows *types.RowConsumption
|
var accRows *types.RowConsumption
|
||||||
|
var traces *types.BlockTrace
|
||||||
|
var err error
|
||||||
|
|
||||||
// do not do CCC checks on follower nodes
|
// do not do CCC checks on follower nodes
|
||||||
if w.isRunning() {
|
if w.isRunning() {
|
||||||
|
|
@ -904,18 +906,18 @@ func (w *worker) commitTransaction(tx *types.Transaction, coinbase common.Addres
|
||||||
// 2.1 when starting handling the first tx, `state.refund` is 0 by default,
|
// 2.1 when starting handling the first tx, `state.refund` is 0 by default,
|
||||||
// 2.2 after tracing, the state is either committed in `core.ApplyTransaction`, or reverted, so the `state.refund` can be cleared,
|
// 2.2 after tracing, the state is either committed in `core.ApplyTransaction`, or reverted, so the `state.refund` can be cleared,
|
||||||
// 2.3 when starting handling the following txs, `state.refund` comes as 0
|
// 2.3 when starting handling the following txs, `state.refund` comes as 0
|
||||||
traces, err := w.current.traceEnv.GetBlockTrace(
|
traces, err = w.current.traceEnv.GetBlockTrace(
|
||||||
types.NewBlockWithHeader(w.current.header).WithBody([]*types.Transaction{tx}, nil),
|
types.NewBlockWithHeader(w.current.header).WithBody([]*types.Transaction{tx}, nil),
|
||||||
)
|
)
|
||||||
// `w.current.traceEnv.State` & `w.current.state` share a same pointer to the state, so only need to revert `w.current.state`
|
// `w.current.traceEnv.State` & `w.current.state` share a same pointer to the state, so only need to revert `w.current.state`
|
||||||
// revert to snapshot for calling `core.ApplyMessage` again, (both `traceEnv.GetBlockTrace` & `core.ApplyTransaction` will call `core.ApplyMessage`)
|
// revert to snapshot for calling `core.ApplyMessage` again, (both `traceEnv.GetBlockTrace` & `core.ApplyTransaction` will call `core.ApplyMessage`)
|
||||||
w.current.state.RevertToSnapshot(snap)
|
w.current.state.RevertToSnapshot(snap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
accRows, err = w.circuitCapacityChecker.ApplyTransaction(traces)
|
accRows, err = w.circuitCapacityChecker.ApplyTransaction(traces)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, traces, err
|
||||||
}
|
}
|
||||||
log.Trace(
|
log.Trace(
|
||||||
"Worker apply ccc for tx result",
|
"Worker apply ccc for tx result",
|
||||||
|
|
@ -931,14 +933,14 @@ func (w *worker) commitTransaction(tx *types.Transaction, coinbase common.Addres
|
||||||
receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &coinbase, w.current.gasPool, w.current.state, w.current.header, tx, &w.current.header.GasUsed, *w.chain.GetVMConfig())
|
receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &coinbase, w.current.gasPool, w.current.state, w.current.header, tx, &w.current.header.GasUsed, *w.chain.GetVMConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.current.state.RevertToSnapshot(snap)
|
w.current.state.RevertToSnapshot(snap)
|
||||||
return nil, err
|
return nil, traces, err
|
||||||
}
|
}
|
||||||
|
|
||||||
w.current.txs = append(w.current.txs, tx)
|
w.current.txs = append(w.current.txs, tx)
|
||||||
w.current.receipts = append(w.current.receipts, receipt)
|
w.current.receipts = append(w.current.receipts, receipt)
|
||||||
w.current.accRows = accRows
|
w.current.accRows = accRows
|
||||||
|
|
||||||
return receipt.Logs, nil
|
return receipt.Logs, traces, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) commitTransactions(txs *types.TransactionsByPriceAndNonce, coinbase common.Address, interrupt *int32) (bool, bool) {
|
func (w *worker) commitTransactions(txs *types.TransactionsByPriceAndNonce, coinbase common.Address, interrupt *int32) (bool, bool) {
|
||||||
|
|
@ -1023,7 +1025,7 @@ loop:
|
||||||
// Start executing the transaction
|
// Start executing the transaction
|
||||||
w.current.state.Prepare(tx.Hash(), w.current.tcount)
|
w.current.state.Prepare(tx.Hash(), w.current.tcount)
|
||||||
|
|
||||||
logs, err := w.commitTransaction(tx, coinbase)
|
logs, traces, err := w.commitTransaction(tx, coinbase)
|
||||||
switch {
|
switch {
|
||||||
case errors.Is(err, core.ErrGasLimitReached) && tx.IsL1MessageTx():
|
case errors.Is(err, core.ErrGasLimitReached) && tx.IsL1MessageTx():
|
||||||
// If this block already contains some L1 messages,
|
// If this block already contains some L1 messages,
|
||||||
|
|
@ -1036,7 +1038,11 @@ loop:
|
||||||
log.Info("Skipping L1 message", "queueIndex", queueIndex, "tx", tx.Hash().String(), "block", w.current.header.Number, "reason", "gas limit exceeded")
|
log.Info("Skipping L1 message", "queueIndex", queueIndex, "tx", tx.Hash().String(), "block", w.current.header.Number, "reason", "gas limit exceeded")
|
||||||
w.current.nextL1MsgIndex = queueIndex + 1
|
w.current.nextL1MsgIndex = queueIndex + 1
|
||||||
txs.Shift()
|
txs.Shift()
|
||||||
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, "gas limit exceeded", w.current.header.Number.Uint64(), nil)
|
if w.config.StoreSkippedTxTraces {
|
||||||
|
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, traces, "gas limit exceeded", w.current.header.Number.Uint64(), nil)
|
||||||
|
} else {
|
||||||
|
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, nil, "gas limit exceeded", w.current.header.Number.Uint64(), nil)
|
||||||
|
}
|
||||||
l1TxGasLimitExceededCounter.Inc(1)
|
l1TxGasLimitExceededCounter.Inc(1)
|
||||||
|
|
||||||
case errors.Is(err, core.ErrGasLimitReached):
|
case errors.Is(err, core.ErrGasLimitReached):
|
||||||
|
|
@ -1113,7 +1119,11 @@ loop:
|
||||||
circuitCapacityReached = false
|
circuitCapacityReached = false
|
||||||
|
|
||||||
// Store skipped transaction in local db
|
// Store skipped transaction in local db
|
||||||
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, "row consumption overflow", w.current.header.Number.Uint64(), nil)
|
if w.config.StoreSkippedTxTraces {
|
||||||
|
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, traces, "row consumption overflow", w.current.header.Number.Uint64(), nil)
|
||||||
|
} else {
|
||||||
|
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, nil, "row consumption overflow", w.current.header.Number.Uint64(), nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case (errors.Is(err, circuitcapacitychecker.ErrUnknown) && tx.IsL1MessageTx()):
|
case (errors.Is(err, circuitcapacitychecker.ErrUnknown) && tx.IsL1MessageTx()):
|
||||||
|
|
@ -1124,7 +1134,11 @@ loop:
|
||||||
log.Info("Skipping L1 message", "queueIndex", queueIndex, "tx", tx.Hash().String(), "block", w.current.header.Number, "reason", "unknown row consumption error")
|
log.Info("Skipping L1 message", "queueIndex", queueIndex, "tx", tx.Hash().String(), "block", w.current.header.Number, "reason", "unknown row consumption error")
|
||||||
w.current.nextL1MsgIndex = queueIndex + 1
|
w.current.nextL1MsgIndex = queueIndex + 1
|
||||||
// TODO: propagate more info about the error from CCC
|
// TODO: propagate more info about the error from CCC
|
||||||
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, "unknown circuit capacity checker error", w.current.header.Number.Uint64(), nil)
|
if w.config.StoreSkippedTxTraces {
|
||||||
|
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, traces, "unknown circuit capacity checker error", w.current.header.Number.Uint64(), nil)
|
||||||
|
} else {
|
||||||
|
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, nil, "unknown circuit capacity checker error", w.current.header.Number.Uint64(), nil)
|
||||||
|
}
|
||||||
l1TxCccUnknownErrCounter.Inc(1)
|
l1TxCccUnknownErrCounter.Inc(1)
|
||||||
|
|
||||||
// Normally we would do `txs.Shift()` here.
|
// Normally we would do `txs.Shift()` here.
|
||||||
|
|
@ -1138,7 +1152,11 @@ loop:
|
||||||
log.Trace("Unknown circuit capacity checker error for L2MessageTx", "tx", tx.Hash().String())
|
log.Trace("Unknown circuit capacity checker error for L2MessageTx", "tx", tx.Hash().String())
|
||||||
log.Info("Skipping L2 message", "tx", tx.Hash().String(), "block", w.current.header.Number, "reason", "unknown row consumption error")
|
log.Info("Skipping L2 message", "tx", tx.Hash().String(), "block", w.current.header.Number, "reason", "unknown row consumption error")
|
||||||
// TODO: propagate more info about the error from CCC
|
// TODO: propagate more info about the error from CCC
|
||||||
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, "unknown circuit capacity checker error", w.current.header.Number.Uint64(), nil)
|
if w.config.StoreSkippedTxTraces {
|
||||||
|
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, traces, "unknown circuit capacity checker error", w.current.header.Number.Uint64(), nil)
|
||||||
|
} else {
|
||||||
|
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, nil, "unknown circuit capacity checker error", w.current.header.Number.Uint64(), nil)
|
||||||
|
}
|
||||||
l2TxCccUnknownErrCounter.Inc(1)
|
l2TxCccUnknownErrCounter.Inc(1)
|
||||||
|
|
||||||
// Normally we would do `txs.Pop()` here.
|
// Normally we would do `txs.Pop()` here.
|
||||||
|
|
@ -1156,7 +1174,11 @@ loop:
|
||||||
queueIndex := tx.AsL1MessageTx().QueueIndex
|
queueIndex := tx.AsL1MessageTx().QueueIndex
|
||||||
log.Info("Skipping L1 message", "queueIndex", queueIndex, "tx", tx.Hash().String(), "block", w.current.header.Number, "reason", "strange error", "err", err)
|
log.Info("Skipping L1 message", "queueIndex", queueIndex, "tx", tx.Hash().String(), "block", w.current.header.Number, "reason", "strange error", "err", err)
|
||||||
w.current.nextL1MsgIndex = queueIndex + 1
|
w.current.nextL1MsgIndex = queueIndex + 1
|
||||||
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, fmt.Sprintf("strange error: %v", err), w.current.header.Number.Uint64(), nil)
|
if w.config.StoreSkippedTxTraces {
|
||||||
|
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, traces, fmt.Sprintf("strange error: %v", err), w.current.header.Number.Uint64(), nil)
|
||||||
|
} else {
|
||||||
|
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, nil, fmt.Sprintf("strange error: %v", err), w.current.header.Number.Uint64(), nil)
|
||||||
|
}
|
||||||
l1TxStrangeErrCounter.Inc(1)
|
l1TxStrangeErrCounter.Inc(1)
|
||||||
}
|
}
|
||||||
txs.Shift()
|
txs.Shift()
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import (
|
||||||
const (
|
const (
|
||||||
VersionMajor = 4 // Major version component of the current release
|
VersionMajor = 4 // Major version component of the current release
|
||||||
VersionMinor = 3 // Minor version component of the current release
|
VersionMinor = 3 // Minor version component of the current release
|
||||||
VersionPatch = 62 // Patch version component of the current release
|
VersionPatch = 63 // Patch version component of the current release
|
||||||
VersionMeta = "sepolia" // Version metadata to append to the version string
|
VersionMeta = "sepolia" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue