@@ -259,6 +259,7 @@ func (l *L2OutputSubmitter) FetchNextOutputInfo(ctx context.Context) (*eth.Outpu
259
259
l .log .Error ("proposer unable to get sync status" , "err" , err )
260
260
return nil , false , err
261
261
}
262
+
262
263
// Use either the finalized or safe head depending on the config. Finalized head is default & safer.
263
264
var currentBlockNumber * big.Int
264
265
if l .allowNonFinalized {
@@ -268,14 +269,14 @@ func (l *L2OutputSubmitter) FetchNextOutputInfo(ctx context.Context) (*eth.Outpu
268
269
}
269
270
// Ensure that we do not submit a block in the future
270
271
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 )
272
273
return nil , false , nil
273
274
}
274
275
275
- return l .fetchOuput (ctx , nextCheckpointBlock )
276
+ return l .fetchOutput (ctx , nextCheckpointBlock )
276
277
}
277
278
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 ) {
279
280
ctx , cancel := context .WithTimeout (ctx , l .networkTimeout )
280
281
defer cancel ()
281
282
output , err := l .rollupClient .OutputAtBlock (ctx , block .Uint64 ())
@@ -321,6 +322,34 @@ func proposeL2OutputTxData(abi *abi.ABI, output *eth.OutputResponse) ([]byte, er
321
322
322
323
// sendTransaction creates & sends transactions through the underlying transaction manager.
323
324
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
+ }
324
353
data , err := l .ProposeL2OutputTxData (output )
325
354
if err != nil {
326
355
return err
@@ -336,7 +365,10 @@ func (l *L2OutputSubmitter) sendTransaction(ctx context.Context, output *eth.Out
336
365
if receipt .Status == types .ReceiptStatusFailed {
337
366
l .log .Error ("proposer tx successfully published but reverted" , "tx_hash" , receipt .TxHash )
338
367
} 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 )
340
372
}
341
373
return nil
342
374
}
@@ -359,10 +391,13 @@ func (l *L2OutputSubmitter) loop() {
359
391
if ! shouldPropose {
360
392
break
361
393
}
362
-
363
394
cCtx , cancel := context .WithTimeout (ctx , 10 * time .Minute )
364
395
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 )
366
401
cancel ()
367
402
break
368
403
}
0 commit comments