Skip to content

Commit

Permalink
Host: avoid spamming stuck L1 transactions (#1941)
Browse files Browse the repository at this point in the history
  • Loading branch information
BedrockSquirrel committed May 31, 2024
1 parent 1562e98 commit 5e69e50
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 11 deletions.
14 changes: 6 additions & 8 deletions go/ethadapter/geth_rpc_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,12 +246,16 @@ func (e *gethRPCClient) FetchLastBatchSeqNo(address gethcommon.Address) (*big.In

// PrepareTransactionToSend takes a txData type and overrides the From, Gas and Gas Price field with current values
func (e *gethRPCClient) PrepareTransactionToSend(ctx context.Context, txData types.TxData, from gethcommon.Address) (types.TxData, error) {
return e.PrepareTransactionToRetry(ctx, txData, from, 0)
nonce, err := e.EthClient().PendingNonceAt(ctx, from)
if err != nil {
return nil, fmt.Errorf("could not get nonce - %w", err)
}
return e.PrepareTransactionToRetry(ctx, txData, from, nonce, 0)
}

// PrepareTransactionToRetry takes a txData type and overrides the From, Gas and Gas Price field with current values
// it bumps the price by a multiplier for retries. retryNumber is zero on first attempt (no multiplier on price)
func (e *gethRPCClient) PrepareTransactionToRetry(ctx context.Context, txData types.TxData, from gethcommon.Address, retryNumber int) (types.TxData, error) {
func (e *gethRPCClient) PrepareTransactionToRetry(ctx context.Context, txData types.TxData, from gethcommon.Address, nonce uint64, retryNumber int) (types.TxData, error) {
unEstimatedTx := types.NewTx(txData)
gasPrice, err := e.EthClient().SuggestGasPrice(ctx)
if err != nil {
Expand Down Expand Up @@ -279,12 +283,6 @@ func (e *gethRPCClient) PrepareTransactionToRetry(ctx context.Context, txData ty
return nil, fmt.Errorf("could not estimate gas - %w", err)
}

// we fetch the current nonce on every retry to avoid any risk of nonce reuse/conflicts
nonce, err := e.EthClient().PendingNonceAt(ctx, from)
if err != nil {
return nil, fmt.Errorf("could not fetch nonce - %w", err)
}

return &types.LegacyTx{
Nonce: nonce,
GasPrice: retryPrice,
Expand Down
2 changes: 1 addition & 1 deletion go/ethadapter/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type EthClient interface {

// PrepareTransactionToSend updates the tx with from address, current nonce and current estimates for the gas and the gas price
PrepareTransactionToSend(ctx context.Context, txData types.TxData, from gethcommon.Address) (types.TxData, error)
PrepareTransactionToRetry(ctx context.Context, txData types.TxData, from gethcommon.Address, retries int) (types.TxData, error)
PrepareTransactionToRetry(ctx context.Context, txData types.TxData, from gethcommon.Address, nonce uint64, retries int) (types.TxData, error)

FetchLastBatchSeqNo(address gethcommon.Address) (*big.Int, error)

Expand Down
9 changes: 8 additions & 1 deletion go/host/l1/publisher.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,12 +391,19 @@ func (p *Publisher) publishTransaction(tx types.TxData) error {

retries := -1

// we keep trying to send the transaction with this nonce until it is included in a block
// note: this is only safe because of the sendingLock guaranteeing only one transaction in-flight at a time
nonce, err := p.ethClient.Nonce(p.hostWallet.Address())
if err != nil {
return fmt.Errorf("could not get nonce for L1 tx: %w", err)
}

// while the publisher service is still alive we keep trying to get the transaction into the L1
for !p.hostStopper.IsStopping() {
retries++ // count each attempt so we can increase gas price

// update the tx gas price before each attempt
tx, err := p.ethClient.PrepareTransactionToRetry(p.sendingContext, tx, p.hostWallet.Address(), retries)
tx, err := p.ethClient.PrepareTransactionToRetry(p.sendingContext, tx, p.hostWallet.Address(), nonce, retries)
if err != nil {
return errors.Wrap(err, "could not estimate gas/gas price for L1 tx")
}
Expand Down
2 changes: 1 addition & 1 deletion integration/ethereummock/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func (m *Node) PrepareTransactionToSend(_ context.Context, txData types.TxData,
}, nil
}

func (m *Node) PrepareTransactionToRetry(ctx context.Context, txData types.TxData, from gethcommon.Address, _ int) (types.TxData, error) {
func (m *Node) PrepareTransactionToRetry(ctx context.Context, txData types.TxData, from gethcommon.Address, _ uint64, _ int) (types.TxData, error) {
return m.PrepareTransactionToSend(ctx, txData, from)
}

Expand Down

0 comments on commit 5e69e50

Please sign in to comment.