Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/angry-ducks-arrive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@eth-optimism/l2geth': patch
---

surface sequencer low-level sequencer execution errors
47 changes: 41 additions & 6 deletions l2geth/miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ const (
staleThreshold = 7
)

var (
// ErrCannotCommitTxn signals that the transaction execution failed
// when attempting to mine a transaction.
//
// NOTE: This error is not expected to occur in regular operation of
// l2geth, rather the actual execution error should be returned to the
// user.
ErrCannotCommitTxn = errors.New("Cannot commit transaction in miner")
)

// environment is the worker's current environment and holds all of the current state information.
type environment struct {
signer types.Signer
Expand Down Expand Up @@ -773,9 +783,13 @@ func (w *worker) commitTransaction(tx *types.Transaction, coinbase common.Addres
}

func (w *worker) commitTransactions(txs *types.TransactionsByPriceAndNonce, coinbase common.Address, interrupt *int32) bool {
return w.commitTransactionsWithError(txs, coinbase, interrupt) != nil
}

func (w *worker) commitTransactionsWithError(txs *types.TransactionsByPriceAndNonce, coinbase common.Address, interrupt *int32) error {
// Short circuit if current is nil
if w.current == nil {
return true
return ErrCannotCommitTxn
}

if w.current.gasPool == nil {
Expand Down Expand Up @@ -803,7 +817,11 @@ func (w *worker) commitTransactions(txs *types.TransactionsByPriceAndNonce, coin
inc: true,
}
}
return w.current.tcount == 0 || atomic.LoadInt32(interrupt) == commitInterruptNewHead
if w.current.tcount == 0 ||
atomic.LoadInt32(interrupt) == commitInterruptNewHead {
return ErrCannotCommitTxn
}
return nil
}
// If we don't have enough gas for any further transactions then we're done
if w.current.gasPool.Gas() < params.TxGas {
Expand Down Expand Up @@ -846,7 +864,7 @@ func (w *worker) commitTransactions(txs *types.TransactionsByPriceAndNonce, coin

case core.ErrNonceTooHigh:
// Reorg notification data race between the transaction pool and miner, skip account =
log.Trace("Skipping account with hight nonce", "sender", from, "nonce", tx.Nonce())
log.Trace("Skipping account with high nonce", "sender", from, "nonce", tx.Nonce())
txs.Pop()

case nil:
Expand All @@ -861,6 +879,20 @@ func (w *worker) commitTransactions(txs *types.TransactionsByPriceAndNonce, coin
log.Debug("Transaction failed, account skipped", "hash", tx.Hash(), "err", err)
txs.Shift()
}

// UsingOVM
// Return specific execution errors directly to the user to
// avoid returning the generic ErrCannotCommitTxnErr. It is safe
// to return the error directly since l2geth only processes at
// most one transaction per block. Currently, we map
// ErrNonceTooHigh to ErrNonceTooLow to match the behavior of
// the mempool, but this mapping will be removed at a later
// point once we decided to expose ErrNonceTooHigh to users.
if err == core.ErrNonceTooHigh {
return core.ErrNonceTooLow
} else if err != nil {
return err
}
}

if !w.isRunning() && len(coalescedLogs) > 0 {
Expand All @@ -883,7 +915,10 @@ func (w *worker) commitTransactions(txs *types.TransactionsByPriceAndNonce, coin
if interrupt != nil {
w.resubmitAdjustCh <- &intervalAdjust{inc: false}
}
return w.current.tcount == 0
if w.current.tcount == 0 {
return ErrCannotCommitTxn
}
return nil
}

// commitNewTx is an OVM addition that mines a block with a single tx in it.
Expand Down Expand Up @@ -945,8 +980,8 @@ func (w *worker) commitNewTx(tx *types.Transaction) error {
acc, _ := types.Sender(w.current.signer, tx)
transactions[acc] = types.Transactions{tx}
txs := types.NewTransactionsByPriceAndNonce(w.current.signer, transactions)
if w.commitTransactions(txs, w.coinbase, nil) {
return errors.New("Cannot commit transaction in miner")
if err := w.commitTransactionsWithError(txs, w.coinbase, nil); err != nil {
return err
}
return w.commit(nil, w.fullTaskHook, tstart)
}
Expand Down
1 change: 1 addition & 0 deletions l2geth/miner/worker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ func TestGenerateBlockAndImportEthash(t *testing.T) {
}

func TestGenerateBlockAndImportClique(t *testing.T) {
t.Skip("OVM breaks this since it aborts after first tx fails")
testGenerateBlockAndImport(t, true)
}

Expand Down