Skip to content

Commit aaa7171

Browse files
author
Roberto Bayardo
committed
fix typo & log more fields for output proposal tx failure
1 parent c939587 commit aaa7171

File tree

3 files changed

+51
-6
lines changed

3 files changed

+51
-6
lines changed

op-e2e/actions/l2_proposer.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ type fakeTxMgr struct {
4444
func (f fakeTxMgr) From() common.Address {
4545
return f.from
4646
}
47+
func (f fakeTxMgr) BlockNumber(_ context.Context) (uint64, error) {
48+
panic("unimplemented")
49+
}
4750
func (f fakeTxMgr) Send(_ context.Context, _ txmgr.TxCandidate) (*types.Receipt, error) {
4851
panic("unimplemented")
4952
}

op-proposer/proposer/l2_output_submitter.go

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ func (l *L2OutputSubmitter) FetchNextOutputInfo(ctx context.Context) (*eth.Outpu
259259
l.log.Error("proposer unable to get sync status", "err", err)
260260
return nil, false, err
261261
}
262+
262263
// Use either the finalized or safe head depending on the config. Finalized head is default & safer.
263264
var currentBlockNumber *big.Int
264265
if l.allowNonFinalized {
@@ -268,14 +269,14 @@ func (l *L2OutputSubmitter) FetchNextOutputInfo(ctx context.Context) (*eth.Outpu
268269
}
269270
// Ensure that we do not submit a block in the future
270271
if currentBlockNumber.Cmp(nextCheckpointBlock) < 0 {
271-
l.log.Info("proposer submission interval has not elapsed", "currentBlockNumber", currentBlockNumber, "nextBlockNumber", nextCheckpointBlock)
272+
l.log.Debug("proposer submission interval has not elapsed", "currentBlockNumber", currentBlockNumber, "nextBlockNumber", nextCheckpointBlock)
272273
return nil, false, nil
273274
}
274275

275-
return l.fetchOuput(ctx, nextCheckpointBlock)
276+
return l.fetchOutput(ctx, nextCheckpointBlock)
276277
}
277278

278-
func (l *L2OutputSubmitter) fetchOuput(ctx context.Context, block *big.Int) (*eth.OutputResponse, bool, error) {
279+
func (l *L2OutputSubmitter) fetchOutput(ctx context.Context, block *big.Int) (*eth.OutputResponse, bool, error) {
279280
ctx, cancel := context.WithTimeout(ctx, l.networkTimeout)
280281
defer cancel()
281282
output, err := l.rollupClient.OutputAtBlock(ctx, block.Uint64())
@@ -321,6 +322,34 @@ func proposeL2OutputTxData(abi *abi.ABI, output *eth.OutputResponse) ([]byte, er
321322

322323
// sendTransaction creates & sends transactions through the underlying transaction manager.
323324
func (l *L2OutputSubmitter) sendTransaction(ctx context.Context, output *eth.OutputResponse) error {
325+
// Wait until l1head is > l1blocknum otherwise the proposal tx will fail when checking the l1
326+
// blockhash. This is because EstimateGas uses "latest" state to execute the transaction by
327+
// default, meaning inside the call, the head block is considered "pending" instead of
328+
// committed. In the case l1blocknum == l1head then, blockhash(l1blocknum) will produce a value
329+
// of 0 within EstimateGas, and the call will fail when the contract checks that l1blockhash
330+
// matches blockhash(l1blocknum).
331+
//
332+
// TODO: Consider forcing EstimateGas to use pending state by specifying block number == -1 in
333+
// the RPC call. This unfortunately is not currently supported by ethclient.
334+
ticker := time.NewTicker(l.pollInterval)
335+
defer ticker.Stop()
336+
l1head, err := l.txMgr.BlockNumber(ctx)
337+
if err != nil {
338+
return err
339+
}
340+
for l1head <= output.Status.HeadL1.Number {
341+
l.log.Debug("waiting for l1 head > l1blocknum", "l1head", l1head, "l1blocknum", output.Status.HeadL1.Number)
342+
select {
343+
case <-ticker.C:
344+
l1head, err = l.txMgr.BlockNumber(ctx)
345+
if err != nil {
346+
return err
347+
}
348+
break
349+
case <-l.done:
350+
return fmt.Errorf("L2OutputSubmitter is done()")
351+
}
352+
}
324353
data, err := l.ProposeL2OutputTxData(output)
325354
if err != nil {
326355
return err
@@ -336,7 +365,10 @@ func (l *L2OutputSubmitter) sendTransaction(ctx context.Context, output *eth.Out
336365
if receipt.Status == types.ReceiptStatusFailed {
337366
l.log.Error("proposer tx successfully published but reverted", "tx_hash", receipt.TxHash)
338367
} else {
339-
l.log.Info("proposer tx successfully published", "tx_hash", receipt.TxHash)
368+
l.log.Info("proposer tx successfully published",
369+
"tx_hash", receipt.TxHash,
370+
"l1blocknum", output.Status.CurrentL1.Number,
371+
"l1blockhash", output.Status.CurrentL1.Hash)
340372
}
341373
return nil
342374
}
@@ -359,10 +391,13 @@ func (l *L2OutputSubmitter) loop() {
359391
if !shouldPropose {
360392
break
361393
}
362-
363394
cCtx, cancel := context.WithTimeout(ctx, 10*time.Minute)
364395
if err := l.sendTransaction(cCtx, output); err != nil {
365-
l.log.Error("Failed to send proposal transaction", "err", err)
396+
l.log.Error("Failed to send proposal transaction",
397+
"err", err,
398+
"l1blocknum", output.Status.CurrentL1.Number,
399+
"l1blockhash", output.Status.CurrentL1.Hash,
400+
"l1head", output.Status.HeadL1.Number)
366401
cancel()
367402
break
368403
}

op-service/txmgr/txmgr.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ type TxManager interface {
4848
// From returns the sending address associated with the instance of the transaction manager.
4949
// It is static for a single instance of a TxManager.
5050
From() common.Address
51+
52+
// BlockNumber returns the most recent block number from the underlying network.
53+
BlockNumber(ctx context.Context) (uint64, error)
5154
}
5255

5356
// ETHBackend is the set of methods that the transaction manager uses to resubmit gas & determine
@@ -116,6 +119,10 @@ func (m *SimpleTxManager) From() common.Address {
116119
return m.cfg.From
117120
}
118121

122+
func (m *SimpleTxManager) BlockNumber(ctx context.Context) (uint64, error) {
123+
return m.backend.BlockNumber(ctx)
124+
}
125+
119126
// TxCandidate is a transaction candidate that can be submitted to ask the
120127
// [TxManager] to construct a transaction with gas price bounds.
121128
type TxCandidate struct {

0 commit comments

Comments
 (0)