From e7a41c1b343c2e311a368e55c3db495e081e29c0 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 a780991f7..dbd15078d 100644 --- a/cmd/flags/proposer.go +++ b/cmd/flags/proposer.go @@ -72,6 +72,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. @@ -88,4 +93,5 @@ var ProposerFlags = MergeFlags(CommonFlags, []cli.Flag{ MaxProposedTxListsPerEpoch, ProposeBlockTxGasLimit, ProposeBlockTxReplacementMultiplier, + ProposeBlockTxGasTipCap, }) diff --git a/proposer/config.go b/proposer/config.go index 5cd153af5..b9ea61a00 100644 --- a/proposer/config.go +++ b/proposer/config.go @@ -3,6 +3,7 @@ package proposer import ( "crypto/ecdsa" "fmt" + "math/big" "strings" "time" @@ -31,6 +32,7 @@ type Config struct { BackOffRetryInterval time.Duration ProposeBlockTxReplacementMultiplier uint64 RPCTimeout *time.Duration + ProposeBlockTxGasTipCap *big.Int } // NewConfigFromCliContext initializes a Config instance from @@ -92,12 +94,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), @@ -116,5 +122,6 @@ func NewConfigFromCliContext(c *cli.Context) (*Config, error) { BackOffRetryInterval: time.Duration(c.Uint64(flags.BackOffRetryInterval.Name)) * time.Second, ProposeBlockTxReplacementMultiplier: proposeBlockTxReplacementMultiplier, RPCTimeout: timeout, + ProposeBlockTxGasTipCap: proposeBlockTxGasTipCap, }, nil } diff --git a/proposer/proposer.go b/proposer/proposer.go index e0a3ec2f8..8d6b05283 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" @@ -54,6 +55,7 @@ type Proposer struct { maxProposedTxListsPerEpoch uint64 proposeBlockTxGasLimit *uint64 txReplacementTipMultiplier uint64 + proposeBlockTxGasTipCap *big.Int // Protocol configurations protocolConfigs *bindings.TaikoDataConfig @@ -90,6 +92,7 @@ func InitFromConfig(ctx context.Context, p *Proposer, cfg *Config) (err error) { p.commitSlot = cfg.CommitSlot p.maxProposedTxListsPerEpoch = cfg.MaxProposedTxListsPerEpoch p.txReplacementTipMultiplier = cfg.ProposeBlockTxReplacementMultiplier + p.proposeBlockTxGasTipCap = cfg.ProposeBlockTxGasTipCap p.ctx = ctx // RPC clients @@ -349,7 +352,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( @@ -357,6 +361,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) @@ -387,7 +401,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