mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 06:36:43 +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.MinerRecommitIntervalFlag,
|
||||
utils.MinerNoVerifyFlag,
|
||||
utils.MinerStoreSkippedTxTracesFlag,
|
||||
utils.NATFlag,
|
||||
utils.NoDiscoverFlag,
|
||||
utils.DiscoveryV5Flag,
|
||||
|
|
|
|||
|
|
@ -192,6 +192,7 @@ var AppHelpFlagGroups = []flags.FlagGroup{
|
|||
utils.MinerExtraDataFlag,
|
||||
utils.MinerRecommitIntervalFlag,
|
||||
utils.MinerNoVerifyFlag,
|
||||
utils.MinerStoreSkippedTxTracesFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -491,6 +491,10 @@ var (
|
|||
Name: "miner.noverify",
|
||||
Usage: "Disable remote sealing verification",
|
||||
}
|
||||
MinerStoreSkippedTxTracesFlag = cli.BoolFlag{
|
||||
Name: "miner.storeskippedtxtraces",
|
||||
Usage: "Store the wrapped traces when storing a skipped tx",
|
||||
}
|
||||
// Account settings
|
||||
UnlockedAccountFlag = cli.StringFlag{
|
||||
Name: "unlock",
|
||||
|
|
@ -1488,6 +1492,9 @@ func setMiner(ctx *cli.Context, cfg *miner.Config) {
|
|||
if ctx.GlobalIsSet(MinerNoVerifyFlag.Name) {
|
||||
cfg.Noverify = ctx.GlobalBool(MinerNoVerifyFlag.Name)
|
||||
}
|
||||
if ctx.GlobalIsSet(MinerStoreSkippedTxTracesFlag.Name) {
|
||||
cfg.StoreSkippedTxTraces = ctx.GlobalBool(MinerStoreSkippedTxTracesFlag.Name)
|
||||
}
|
||||
if ctx.GlobalIsSet(LegacyMinerGasTargetFlag.Name) {
|
||||
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()
|
||||
skippedTx := types.NewTx(&l1msg)
|
||||
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
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package rawdb
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"sync"
|
||||
|
||||
|
|
@ -61,8 +62,50 @@ type SkippedTransaction struct {
|
|||
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.
|
||||
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
|
||||
if blockHash == nil {
|
||||
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}
|
||||
bytes, err := rlp.EncodeToBytes(stx)
|
||||
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 {
|
||||
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.
|
||||
func ReadSkippedTransaction(db ethdb.Reader, txHash common.Hash) *SkippedTransaction {
|
||||
func ReadSkippedTransaction(db ethdb.Reader, txHash common.Hash) *SkippedTransactionV2 {
|
||||
data := readSkippedTransactionRLP(db, txHash)
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
var stxV2 SkippedTransactionV2
|
||||
var stx SkippedTransaction
|
||||
if err := rlp.Decode(bytes.NewReader(data), &stx); err != nil {
|
||||
log.Crit("Invalid skipped transaction RLP", "hash", txHash.String(), "data", data, "err", err)
|
||||
if err := rlp.Decode(bytes.NewReader(data), &stxV2); 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)
|
||||
}
|
||||
stxV2.Tx = stx.Tx
|
||||
stxV2.Reason = stx.Reason
|
||||
stxV2.BlockNumber = stx.BlockNumber
|
||||
stxV2.BlockHash = stx.BlockHash
|
||||
}
|
||||
if stx.BlockHash != nil && *stx.BlockHash == (common.Hash{}) {
|
||||
stx.BlockHash = nil
|
||||
|
||||
if stxV2.BlockHash != nil && *stxV2.BlockHash == (common.Hash{}) {
|
||||
stxV2.BlockHash = nil
|
||||
}
|
||||
return &stx
|
||||
return &stxV2
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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...
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
|
@ -136,7 +187,7 @@ func WriteSkippedTransaction(db ethdb.Database, tx *types.Transaction, reason st
|
|||
|
||||
// update in a batch
|
||||
batch := db.NewBatch()
|
||||
writeSkippedTransaction(db, tx, reason, blockNumber, blockHash)
|
||||
writeSkippedTransaction(db, tx, traces, reason, blockNumber, blockHash)
|
||||
writeSkippedTransactionHash(db, index, tx.Hash())
|
||||
writeNumSkippedTransactions(db, index+1)
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,17 @@ func newTestTransaction(queueIndex uint64) *types.Transaction {
|
|||
func TestReadWriteSkippedTransactionNoIndex(t *testing.T) {
|
||||
tx := newTestTransaction(123)
|
||||
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())
|
||||
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)
|
||||
|
|
@ -54,7 +64,7 @@ func TestReadWriteSkippedTransactionNoIndex(t *testing.T) {
|
|||
func TestReadWriteSkippedTransaction(t *testing.T) {
|
||||
tx := newTestTransaction(123)
|
||||
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)
|
||||
|
|
@ -78,7 +88,7 @@ func TestSkippedTransactionConcurrentUpdate(t *testing.T) {
|
|||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
WriteSkippedTransaction(db, tx, "random reason", 1, &common.Hash{1})
|
||||
WriteSkippedTransaction(db, tx, nil, "random reason", 1, &common.Hash{1})
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
|
|
@ -100,12 +110,12 @@ func TestIterateSkippedTransactions(t *testing.T) {
|
|||
}
|
||||
|
||||
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
|
||||
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)
|
||||
defer it.Release()
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package eth
|
|||
import (
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
|
@ -720,6 +721,9 @@ type RPCTransaction struct {
|
|||
SkipReason string `json:"skipReason"`
|
||||
SkipBlockNumber *hexutil.Big `json:"skipBlockNumber"`
|
||||
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.
|
||||
|
|
@ -733,6 +737,11 @@ func (api *ScrollAPI) GetSkippedTransaction(ctx context.Context, hash common.Has
|
|||
rpcTx.SkipReason = stx.Reason
|
||||
rpcTx.SkipBlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(stx.BlockNumber))
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@ type Config struct {
|
|||
GasPrice *big.Int // Minimum gas price for mining a transaction
|
||||
Recommit time.Duration // The time interval for miner to re-create mining work.
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -884,8 +884,10 @@ func (w *worker) updateSnapshot() {
|
|||
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 traces *types.BlockTrace
|
||||
var err error
|
||||
|
||||
// do not do CCC checks on follower nodes
|
||||
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.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
|
||||
traces, err := w.current.traceEnv.GetBlockTrace(
|
||||
traces, err = w.current.traceEnv.GetBlockTrace(
|
||||
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`
|
||||
// revert to snapshot for calling `core.ApplyMessage` again, (both `traceEnv.GetBlockTrace` & `core.ApplyTransaction` will call `core.ApplyMessage`)
|
||||
w.current.state.RevertToSnapshot(snap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
accRows, err = w.circuitCapacityChecker.ApplyTransaction(traces)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, traces, err
|
||||
}
|
||||
log.Trace(
|
||||
"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())
|
||||
if err != nil {
|
||||
w.current.state.RevertToSnapshot(snap)
|
||||
return nil, err
|
||||
return nil, traces, err
|
||||
}
|
||||
|
||||
w.current.txs = append(w.current.txs, tx)
|
||||
w.current.receipts = append(w.current.receipts, receipt)
|
||||
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) {
|
||||
|
|
@ -1023,7 +1025,7 @@ loop:
|
|||
// Start executing the transaction
|
||||
w.current.state.Prepare(tx.Hash(), w.current.tcount)
|
||||
|
||||
logs, err := w.commitTransaction(tx, coinbase)
|
||||
logs, traces, err := w.commitTransaction(tx, coinbase)
|
||||
switch {
|
||||
case errors.Is(err, core.ErrGasLimitReached) && tx.IsL1MessageTx():
|
||||
// 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")
|
||||
w.current.nextL1MsgIndex = queueIndex + 1
|
||||
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)
|
||||
|
||||
case errors.Is(err, core.ErrGasLimitReached):
|
||||
|
|
@ -1113,7 +1119,11 @@ loop:
|
|||
circuitCapacityReached = false
|
||||
|
||||
// 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()):
|
||||
|
|
@ -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")
|
||||
w.current.nextL1MsgIndex = queueIndex + 1
|
||||
// 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)
|
||||
|
||||
// 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.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
|
||||
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)
|
||||
|
||||
// Normally we would do `txs.Pop()` here.
|
||||
|
|
@ -1156,7 +1174,11 @@ loop:
|
|||
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)
|
||||
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)
|
||||
}
|
||||
txs.Shift()
|
||||
|
|
|
|||
|
|
@ -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 = 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
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue