From e40115b97002661def8eed8dfb768ad28c19f0ea Mon Sep 17 00:00:00 2001 From: David Date: Sat, 5 Aug 2023 02:23:14 +0800 Subject: [PATCH] feat(proposer): add `--proposeBlockTxGasTipCap` flag (#349) --- cmd/flags/proposer.go | 6 ++++++ proposer/config.go | 9 ++++++++- proposer/proposer.go | 18 ++++++++++++++++-- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/cmd/flags/proposer.go b/cmd/flags/proposer.go index 3132565fe..db3792255 100644 --- a/cmd/flags/proposer.go +++ b/cmd/flags/proposer.go @@ -59,6 +59,11 @@ var ( Usage: "Gas tip multiplier when replacing a TaikoL1.proposeBlock transaction with same nonce", Category: proposerCategory, } + ProposeBlockTxGasTipCap = &cli.Uint64Flag{ + Name: "proposeBlockTxGasTipCap", + Usage: "Gas tip cap (in wei) for a TaikoL1.proposeBlock transaction when doing the transaction replacement", + Category: proposerCategory, + } ) // All proposer flags. @@ -73,4 +78,5 @@ var ProposerFlags = MergeFlags(CommonFlags, []cli.Flag{ MaxProposedTxListsPerEpoch, ProposeBlockTxGasLimit, ProposeBlockTxReplacementMultiplier, + ProposeBlockTxGasTipCap, }) diff --git a/proposer/config.go b/proposer/config.go index c7e9465ea..799c90077 100644 --- a/proposer/config.go +++ b/proposer/config.go @@ -3,6 +3,7 @@ package proposer import ( "crypto/ecdsa" "fmt" + "math/big" "strings" "time" @@ -30,6 +31,7 @@ type Config struct { ProposeBlockTxReplacementMultiplier uint64 RPCTimeout *time.Duration WaitReceiptTimeout time.Duration + ProposeBlockTxGasTipCap *big.Int } // NewConfigFromCliContext initializes a Config instance from @@ -91,12 +93,16 @@ func NewConfigFromCliContext(c *cli.Context) (*Config, error) { } var timeout *time.Duration - if c.IsSet(flags.RPCTimeout.Name) { duration := time.Duration(c.Uint64(flags.RPCTimeout.Name)) * time.Second timeout = &duration } + var proposeBlockTxGasTipCap *big.Int + if c.IsSet(flags.ProposeBlockTxGasTipCap.Name) { + proposeBlockTxGasTipCap = new(big.Int).SetUint64(c.Uint64(flags.ProposeBlockTxGasTipCap.Name)) + } + return &Config{ L1Endpoint: c.String(flags.L1WSEndpoint.Name), L2Endpoint: c.String(flags.L2HTTPEndpoint.Name), @@ -114,5 +120,6 @@ func NewConfigFromCliContext(c *cli.Context) (*Config, error) { ProposeBlockTxReplacementMultiplier: proposeBlockTxReplacementMultiplier, RPCTimeout: timeout, WaitReceiptTimeout: time.Duration(c.Uint64(flags.WaitReceiptTimeout.Name)) * time.Second, + ProposeBlockTxGasTipCap: proposeBlockTxGasTipCap, }, nil } diff --git a/proposer/proposer.go b/proposer/proposer.go index 729b93cad..095adcc90 100644 --- a/proposer/proposer.go +++ b/proposer/proposer.go @@ -15,6 +15,7 @@ import ( "github.com/cenkalti/backoff/v4" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" @@ -51,6 +52,7 @@ type Proposer struct { maxProposedTxListsPerEpoch uint64 proposeBlockTxGasLimit *uint64 txReplacementTipMultiplier uint64 + proposeBlockTxGasTipCap *big.Int // Protocol configurations protocolConfigs *bindings.TaikoDataConfig @@ -88,6 +90,7 @@ func InitFromConfig(ctx context.Context, p *Proposer, cfg *Config) (err error) { p.localsOnly = cfg.LocalAddressesOnly p.maxProposedTxListsPerEpoch = cfg.MaxProposedTxListsPerEpoch p.txReplacementTipMultiplier = cfg.ProposeBlockTxReplacementMultiplier + p.proposeBlockTxGasTipCap = cfg.ProposeBlockTxGasTipCap p.ctx = ctx p.waitReceiptTimeout = cfg.WaitReceiptTimeout @@ -353,7 +356,8 @@ func (p *Proposer) sendProposeBlockTx( "Original transaction to replace", "sender", p.l1ProposerAddress, "nonce", nonce, - "tx", originalTx, + "gasTipCap", originalTx.GasTipCap(), + "gasFeeCap", originalTx.GasFeeCap(), ) opts.GasTipCap = new(big.Int).Mul( @@ -361,6 +365,16 @@ func (p *Proposer) sendProposeBlockTx( new(big.Int).SetUint64(p.txReplacementTipMultiplier), ) } + + if p.proposeBlockTxGasTipCap != nil && opts.GasTipCap.Cmp(p.proposeBlockTxGasTipCap) > 0 { + log.Info( + "New gasTipCap exceeds limit, keep waiting", + "multiplier", p.txReplacementTipMultiplier, + "newGasTipCap", opts.GasTipCap, + "maxTipCap", p.proposeBlockTxGasTipCap, + ) + return nil, txpool.ErrReplaceUnderpriced + } } proposeTx, err := p.rpc.TaikoL1.ProposeBlock(opts, inputs, txListBytes) @@ -391,7 +405,7 @@ func (p *Proposer) ProposeTxList( } if tx, err = p.sendProposeBlockTx(ctx, meta, txListBytes, nonce, isReplacement); err != nil { log.Warn("Failed to send propose block transaction, retrying", "error", err) - if strings.Contains(err.Error(), "replacement transaction underpriced") { + if strings.Contains(err.Error(), txpool.ErrReplaceUnderpriced.Error()) { isReplacement = true } else { isReplacement = false