Skip to content
This repository has been archived by the owner on May 11, 2024. It is now read-only.

Commit

Permalink
feat(proposer): handle transaction replacement underpriced error
Browse files Browse the repository at this point in the history
  • Loading branch information
davidtaikocha committed Jul 19, 2023
1 parent 9eefc8d commit 8bc63c4
Showing 1 changed file with 58 additions and 21 deletions.
79 changes: 58 additions & 21 deletions proposer/proposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"math"
"math/big"
"math/rand"
"strings"
"sync"
"time"

Expand All @@ -27,8 +28,10 @@ import (
)

var (
errNoNewTxs = errors.New("no new transactions")
waitReceiptTimeout = 1 * time.Minute
errNoNewTxs = errors.New("no new transactions")
waitReceiptTimeout = 1 * time.Minute
maxSendProposeBlockTxRetry = 10
txReplacementTipMultiplier = 2
)

// Proposer keep proposing new transactions from L2 execution engine's tx pool at a fixed interval.
Expand Down Expand Up @@ -278,36 +281,70 @@ func (p *Proposer) ProposeTxList(
txNum uint,
nonce *uint64,
) error {
if p.minBlockGasLimit != nil && meta.GasLimit < uint32(*p.minBlockGasLimit) {
meta.GasLimit = uint32(*p.minBlockGasLimit)
}
sendProposeBlockTx := func(isReplacement bool) (*types.Transaction, error) {
if p.minBlockGasLimit != nil && meta.GasLimit < uint32(*p.minBlockGasLimit) {
meta.GasLimit = uint32(*p.minBlockGasLimit)
}

// Propose the transactions list
inputs, err := encoding.EncodeProposeBlockInput(meta)
if err != nil {
return err
}
// Propose the transactions list
inputs, err := encoding.EncodeProposeBlockInput(meta)
if err != nil {
return nil, err
}

opts, err := getTxOpts(ctx, p.rpc.L1, p.l1ProposerPrivKey, p.rpc.L1ChainID)
if err != nil {
return err
}
if nonce != nil {
opts.Nonce = new(big.Int).SetUint64(*nonce)
opts, err := getTxOpts(ctx, p.rpc.L1, p.l1ProposerPrivKey, p.rpc.L1ChainID)
if err != nil {
return nil, err
}
if nonce != nil {
opts.Nonce = new(big.Int).SetUint64(*nonce)
}
if p.proposeBlockTxGasLimit != nil {
opts.GasLimit = *p.proposeBlockTxGasLimit
}

if isReplacement {
opts.GasTipCap = new(big.Int).Mul(opts.GasTipCap, new(big.Int).SetUint64(uint64(txReplacementTipMultiplier)))
}

proposeTx, err := p.rpc.TaikoL1.ProposeBlock(opts, inputs, txListBytes)
if err != nil {
return nil, encoding.TryParsingCustomError(err)
}

return proposeTx, nil
}
if p.proposeBlockTxGasLimit != nil {
opts.GasLimit = *p.proposeBlockTxGasLimit

var (
try = 0
tx *types.Transaction
isReplacement bool
err error
)

for try < maxSendProposeBlockTxRetry {
if tx, err = sendProposeBlockTx(isReplacement); err != nil {
try += 1
log.Warn("Failed to send propose block transaction, retrying", "error", err)
if strings.Contains(err.Error(), "replacement transaction underpriced") {
isReplacement = true
} else {
isReplacement = false
}
continue
}

break
}

proposeTx, err := p.rpc.TaikoL1.ProposeBlock(opts, inputs, txListBytes)
if err != nil {
return encoding.TryParsingCustomError(err)
return err
}

ctxWithTimeout, cancel := context.WithTimeout(ctx, waitReceiptTimeout)
defer cancel()

if _, err := rpc.WaitReceipt(ctxWithTimeout, p.rpc.L1, proposeTx); err != nil {
if _, err := rpc.WaitReceipt(ctxWithTimeout, p.rpc.L1, tx); err != nil {
return err
}

Expand Down

0 comments on commit 8bc63c4

Please sign in to comment.