Skip to content

Commit

Permalink
include L2 txs in skipped index
Browse files Browse the repository at this point in the history
  • Loading branch information
Thegaram committed Aug 22, 2023
1 parent adfb3f4 commit e9c6882
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 58 deletions.
2 changes: 1 addition & 1 deletion core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.WriteSkippedL1Message(v.db, skippedTx, "unknown", block.NumberU64(), &blockHash)
rawdb.WriteSkippedTransaction(v.db, skippedTx, "unknown", block.NumberU64(), &blockHash)
}

queueIndex = txQueueIndex + 1
Expand Down
64 changes: 32 additions & 32 deletions core/rawdb/accessors_skipped_txs.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,31 @@ import (
// mutex used to avoid concurrent updates of NumSkippedL1Messages
var mu sync.Mutex

// WriteNumSkippedL1Messages writes the number of skipped L1 messages to the database.
func WriteNumSkippedL1Messages(db ethdb.KeyValueWriter, numSkipped uint64) {
// writeNumSkippedTransactions writes the number of skipped L1 transactions to the database.
func writeNumSkippedTransactions(db ethdb.KeyValueWriter, numSkipped uint64) {
value := big.NewInt(0).SetUint64(numSkipped).Bytes()

if err := db.Put(numSkippedL1MessagesKey, value); err != nil {
log.Crit("Failed to update the number of skipped L1 messages", "err", err)
if err := db.Put(numSkippedTransactionsKey, value); err != nil {
log.Crit("Failed to update the number of skipped L1 transactions", "err", err)
}
}

// ReadNumSkippedL1Messages retrieves the number of skipped messages.
func ReadNumSkippedL1Messages(db ethdb.Reader) uint64 {
data, err := db.Get(numSkippedL1MessagesKey)
// ReadNumSkippedTransactions retrieves the number of skipped messages.
func ReadNumSkippedTransactions(db ethdb.Reader) uint64 {
data, err := db.Get(numSkippedTransactionsKey)
if err != nil && isNotFoundErr(err) {
return 0
}
if err != nil {
log.Crit("Failed to read number of skipped L1 messages from database", "err", err)
log.Crit("Failed to read number of skipped L1 transactions from database", "err", err)
}
if len(data) == 0 {
return 0
}

number := new(big.Int).SetBytes(data)
if !number.IsUint64() {
log.Crit("Unexpected number of skipped L1 messages in database", "number", number)
log.Crit("Unexpected number of skipped L1 transactions in database", "number", number)
}
return number.Uint64()
}
Expand All @@ -61,8 +61,8 @@ type SkippedTransaction struct {
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) {
// writeSkippedTransaction writes a skipped transaction to the database.
func writeSkippedTransaction(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{}
Expand All @@ -77,8 +77,8 @@ func WriteSkippedTransaction(db ethdb.KeyValueWriter, tx *types.Transaction, rea
}
}

// ReadSkippedTransactionRLP retrieves a skipped transaction in its raw RLP database encoding.
func ReadSkippedTransactionRLP(db ethdb.Reader, txHash common.Hash) rlp.RawValue {
// readSkippedTransactionRLP retrieves a skipped transaction in its raw RLP database encoding.
func readSkippedTransactionRLP(db ethdb.Reader, txHash common.Hash) rlp.RawValue {
data, err := db.Get(SkippedTransactionKey(txHash))
if err != nil && isNotFoundErr(err) {
return nil
Expand All @@ -91,7 +91,7 @@ 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 {
data := ReadSkippedTransactionRLP(db, txHash)
data := readSkippedTransactionRLP(db, txHash)
if len(data) == 0 {
return nil
}
Expand All @@ -105,49 +105,49 @@ func ReadSkippedTransaction(db ethdb.Reader, txHash common.Hash) *SkippedTransac
return &stx
}

// WriteSkippedL1MessageHash writes the hash of a skipped L1 message to the database.
func WriteSkippedL1MessageHash(db ethdb.KeyValueWriter, index uint64, txHash common.Hash) {
if err := db.Put(SkippedL1MessageHashKey(index), txHash[:]); err != nil {
log.Crit("Failed to store skipped transaction index", "index", index, "hash", txHash.String(), "err", err)
// writeSkippedTransactionHash writes the hash of a skipped transaction to the database.
func writeSkippedTransactionHash(db ethdb.KeyValueWriter, index uint64, txHash common.Hash) {
if err := db.Put(SkippedTransactionHashKey(index), txHash[:]); err != nil {
log.Crit("Failed to store skipped transaction hash", "index", index, "hash", txHash.String(), "err", err)
}
}

// ReadSkippedL1MessageHash retrieves the hash of a skipped L1 message by its index.
// ReadSkippedL1MessageHash retrieves the hash of a skipped transaction by its index.
func ReadSkippedL1MessageHash(db ethdb.Reader, index uint64) *common.Hash {
data, err := db.Get(SkippedL1MessageHashKey(index))
data, err := db.Get(SkippedTransactionHashKey(index))
if err != nil && isNotFoundErr(err) {
return nil
}
if err != nil {
log.Crit("Failed to load skipped L1 message index index", "index", index, "err", err)
log.Crit("Failed to load skipped transaction hash", "index", index, "err", err)
}
hash := common.BytesToHash(data)
return &hash
}

// WriteSkippedL1Message writes a skipped L1 message 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.
func WriteSkippedL1Message(db ethdb.Database, tx *types.Transaction, reason string, blockNumber uint64, blockHash *common.Hash) {
func WriteSkippedTransaction(db ethdb.Database, tx *types.Transaction, reason string, blockNumber uint64, blockHash *common.Hash) {
// this method is not accessed concurrently, but just to be sure...
mu.Lock()
defer mu.Unlock()

index := ReadNumSkippedL1Messages(db)
index := ReadNumSkippedTransactions(db)

// update in a batch
batch := db.NewBatch()
WriteSkippedTransaction(db, tx, reason, blockNumber, blockHash)
WriteSkippedL1MessageHash(db, index, tx.Hash())
WriteNumSkippedL1Messages(db, index+1)
writeSkippedTransaction(db, tx, reason, blockNumber, blockHash)
writeSkippedTransactionHash(db, index, tx.Hash())
writeNumSkippedTransactions(db, index+1)

// write to DB
if err := batch.Write(); err != nil {
log.Crit("Failed to store skipped L1 message", "hash", tx.Hash().String(), "err", err)
log.Crit("Failed to store skipped transaction", "hash", tx.Hash().String(), "err", err)
}
}

// SkippedTransactionIterator is a wrapper around ethdb.Iterator that
// allows us to iterate over skipped L1 message hashes in the database.
// allows us to iterate over skipped transaction hashes in the database.
// It implements an interface similar to ethdb.Iterator.
type SkippedTransactionIterator struct {
inner ethdb.Iterator
Expand All @@ -156,7 +156,7 @@ type SkippedTransactionIterator struct {
}

// IterateSkippedTransactionsFrom creates a SkippedTransactionIterator that iterates
// over all skipped L1 message hashes in the database starting at the provided index.
// over all skipped transaction hashes in the database starting at the provided index.
func IterateSkippedTransactionsFrom(db ethdb.Database, index uint64) SkippedTransactionIterator {
start := encodeBigEndian(index)
it := db.NewIterator(skippedL1MessageHashPrefix, start)
Expand All @@ -182,15 +182,15 @@ func (it *SkippedTransactionIterator) Next() bool {
return false
}

// Index returns the index of the current skipped L1 message hash.
// Index returns the index of the current skipped transaction hash.
func (it *SkippedTransactionIterator) Index() uint64 {
key := it.inner.Key()
raw := key[len(skippedL1MessageHashPrefix) : len(skippedL1MessageHashPrefix)+8]
index := binary.BigEndian.Uint64(raw)
return index
}

// TransactionHash returns the current skipped L1 message hash.
// TransactionHash returns the current skipped transaction hash.
func (it *SkippedTransactionIterator) TransactionHash() common.Hash {
data := it.inner.Value()
return common.BytesToHash(data)
Expand Down
18 changes: 9 additions & 9 deletions core/rawdb/accessors_skipped_txs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ func TestReadWriteNumSkippedL1Messages(t *testing.T) {

db := NewMemoryDatabase()
for _, num := range blockNumbers {
WriteNumSkippedL1Messages(db, num)
got := ReadNumSkippedL1Messages(db)
writeNumSkippedTransactions(db, num)
got := ReadNumSkippedTransactions(db)

if got != num {
t.Fatal("Num L1 messages mismatch", "expected", num, "got", got)
Expand All @@ -44,7 +44,7 @@ func newTestTransaction(queueIndex uint64) *types.Transaction {
func TestReadWriteSkippedTransaction(t *testing.T) {
tx := newTestTransaction(123)
db := NewMemoryDatabase()
WriteSkippedTransaction(db, tx, "random reason", 1, &common.Hash{1})
writeSkippedTransaction(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)
Expand All @@ -54,12 +54,12 @@ func TestReadWriteSkippedTransaction(t *testing.T) {
func TestReadWriteSkippedL1Message(t *testing.T) {
tx := newTestTransaction(123)
db := NewMemoryDatabase()
WriteSkippedL1Message(db, tx, "random reason", 1, &common.Hash{1})
WriteSkippedTransaction(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)
}
count := ReadNumSkippedL1Messages(db)
count := ReadNumSkippedTransactions(db)
if count != 1 {
t.Fatal("Skipped transaction count mismatch", "expected", 1, "got", count)
}
Expand All @@ -78,11 +78,11 @@ func TestSkippedL1MessageConcurrentUpdate(t *testing.T) {
wg.Add(1)
go func() {
defer wg.Done()
WriteSkippedL1Message(db, tx, "random reason", 1, &common.Hash{1})
WriteSkippedTransaction(db, tx, "random reason", 1, &common.Hash{1})
}()
}
wg.Wait()
got := ReadNumSkippedL1Messages(db)
got := ReadNumSkippedTransactions(db)
if got != uint64(count) {
t.Fatal("Skipped transaction count mismatch", "expected", count, "got", got)
}
Expand All @@ -100,12 +100,12 @@ func TestIterateSkippedL1Messages(t *testing.T) {
}

for _, tx := range txs {
WriteSkippedL1Message(db, tx, "random reason", 1, &common.Hash{1})
WriteSkippedTransaction(db, tx, "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, "random reason", 1, &common.Hash{1})

it := IterateSkippedTransactionsFrom(db, 2)
defer it.Release()
Expand Down
6 changes: 3 additions & 3 deletions core/rawdb/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ var (
rowConsumptionPrefix = []byte("rc") // rowConsumptionPrefix + hash -> row consumption by block

// Skipped transactions
numSkippedL1MessagesKey = []byte("NumberOfSkippedL1Messages")
numSkippedTransactionsKey = []byte("NumberOfSkippedL1Messages")
skippedTransactionPrefix = []byte("skip") // skippedTransactionPrefix + tx hash -> skipped transaction
skippedL1MessageHashPrefix = []byte("sh") // skippedL1MessageHashPrefix + index -> tx hash
)
Expand Down Expand Up @@ -279,7 +279,7 @@ func SkippedTransactionKey(txHash common.Hash) []byte {
return append(skippedTransactionPrefix, txHash.Bytes()...)
}

// SkippedL1MessageHashKey = skippedL1MessageHashPrefix + index (uint64 big endian)
func SkippedL1MessageHashKey(index uint64) []byte {
// SkippedTransactionHashKey = skippedL1MessageHashPrefix + index (uint64 big endian)
func SkippedTransactionHashKey(index uint64) []byte {
return append(skippedL1MessageHashPrefix, encodeBigEndian(index)...)
}
10 changes: 5 additions & 5 deletions eth/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -709,9 +709,9 @@ func (api *ScrollAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumb
return nil, err
}

// GetNumSkippedL1Messages returns the number of skipped L1 messages.
func (api *ScrollAPI) GetNumSkippedL1Messages(ctx context.Context) (uint64, error) {
return rawdb.ReadNumSkippedL1Messages(api.eth.ChainDb()), nil
// GetNumSkippedTransactions returns the number of skipped transactions.
func (api *ScrollAPI) GetNumSkippedTransactions(ctx context.Context) (uint64, error) {
return rawdb.ReadNumSkippedTransactions(api.eth.ChainDb()), nil
}

// RPCTransaction is the standard RPC transaction return type with some additional skip-related fields.
Expand All @@ -736,8 +736,8 @@ func (api *ScrollAPI) GetSkippedTransaction(ctx context.Context, hash common.Has
return &rpcTx, nil
}

// GetSkippedL1MessageHashes returns a list of skipped L1 message hashes between the two indices provided (inclusive).
func (api *ScrollAPI) GetSkippedL1MessageHashes(ctx context.Context, from uint64, to uint64) ([]common.Hash, error) {
// GetSkippedTransactionHashes returns a list of skipped transaction hashes between the two indices provided (inclusive).
func (api *ScrollAPI) GetSkippedTransactionHashes(ctx context.Context, from uint64, to uint64) ([]common.Hash, error) {
it := rawdb.IterateSkippedTransactionsFrom(api.eth.ChainDb(), from)
defer it.Release()

Expand Down
11 changes: 4 additions & 7 deletions miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -1028,7 +1028,7 @@ 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.WriteSkippedL1Message(w.eth.ChainDb(), tx, "gas limit exceeded", w.current.header.Number.Uint64(), nil)
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, "gas limit exceeded", w.current.header.Number.Uint64(), nil)

case errors.Is(err, core.ErrGasLimitReached):
// Pop the current out-of-gas transaction without shifting in the next from the account
Expand Down Expand Up @@ -1080,7 +1080,7 @@ loop:
log.Trace("Circuit capacity limit reached for a single tx", "tx", tx.Hash().String(), "queueIndex", queueIndex)
log.Info("Skipping L1 message", "queueIndex", queueIndex, "tx", tx.Hash().String(), "block", w.current.header.Number, "reason", "row consumption overflow")
w.current.nextL1MsgIndex = queueIndex + 1
rawdb.WriteSkippedL1Message(w.eth.ChainDb(), tx, "row consumption overflow", w.current.header.Number.Uint64(), nil)
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, "row consumption overflow", w.current.header.Number.Uint64(), nil)

// after `ErrTxRowConsumptionOverflow`, ccc might not revert updates
// associated with this transaction so we cannot pack more transactions.
Expand All @@ -1092,9 +1092,6 @@ loop:
// Circuit capacity check: L2MessageTx row consumption too high, skip the account.
// This is also useful for skipping "problematic" L2MessageTxs.
log.Trace("Circuit capacity limit reached for a single tx", "tx", tx.Hash().String())

// store info about overflowing L2 txs for further analysis,
// but do not include L2 txs in the skipped index and count
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, "row consumption overflow", w.current.header.Number.Uint64(), nil)

// after `ErrTxRowConsumptionOverflow`, ccc might not revert updates
Expand All @@ -1111,7 +1108,7 @@ 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.WriteSkippedL1Message(w.eth.ChainDb(), tx, "unknown row consumption error", w.current.header.Number.Uint64(), nil)
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, "unknown row consumption error", w.current.header.Number.Uint64(), nil)

// after `ErrUnknown`, ccc might not revert updates associated
// with this transaction so we cannot pack more transactions.
Expand All @@ -1137,7 +1134,7 @@ 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.WriteSkippedL1Message(w.eth.ChainDb(), tx, fmt.Sprintf("strange error: %v", err), w.current.header.Number.Uint64(), nil)
rawdb.WriteSkippedTransaction(w.eth.ChainDb(), tx, fmt.Sprintf("strange error: %v", err), w.current.header.Number.Uint64(), nil)
}
txs.Shift()
}
Expand Down
2 changes: 1 addition & 1 deletion miner/worker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1064,7 +1064,7 @@ func TestSkippedL1MessageDatabaseEntries(t *testing.T) {
assert.Equal(block.NumberU64(), stx.BlockNumber)
assert.Nil(stx.BlockHash)

numSkipped := rawdb.ReadNumSkippedL1Messages(db)
numSkipped := rawdb.ReadNumSkippedTransactions(db)
assert.Equal(uint64(1), numSkipped)

hash2 := rawdb.ReadSkippedL1MessageHash(db, 0)
Expand Down

0 comments on commit e9c6882

Please sign in to comment.