From c521f913cfaf46d6a907e79e59ea086d07436178 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Thu, 5 Dec 2024 19:27:44 +0800 Subject: [PATCH 01/11] fix(GPO): increase min suggested tip to 100 wei --- eth/gasprice/gasprice.go | 15 ++++++++------- eth/gasprice/gasprice_test.go | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go index dab0e06d3200..f2002d3b871c 100644 --- a/eth/gasprice/gasprice.go +++ b/eth/gasprice/gasprice.go @@ -195,13 +195,14 @@ func (oracle *Oracle) SuggestTipCap(ctx context.Context) (*big.Int, error) { // high-priced txs are causing the suggested tip cap to be high. pendingTxCount, _ := oracle.backend.StatsWithMinBaseFee(head.BaseFee) if pendingTxCount < oracle.congestedThreshold { - // Before Curie (EIP-1559), we need to return the total suggested gas price. After Curie we return 2 wei as the tip cap, - // as the base fee is set separately or added manually for legacy transactions. - // 1. Set price to at least 1 as otherwise tx with a 0 tip might be filtered out by the default mempool config. - // 2. Since oracle.ignoreprice was set to 2 (DefaultIgnorePrice) before by default, we need to set the price - // to 2 to avoid filtering in oracle.getBlockValues() by nodes that did not yet update to this version. - // In the future we can set the price to 1 wei. - price := big.NewInt(2) + // Before Curie (EIP-1559), we need to return the total suggested gas price (base fee + tip cap). + // After Curie, a minimum tip cap of 100 wei is used to avoid issues with extremely low values like 1 wei: + // 1. txpool protections: + // - txpool commonly prevents replacing transactions with the same tip cap. + // - A 1 wei tip may fail to increase (e.g., 1.1x rounds down to 1 wei) due to integer arithmetic. + // 2. Negligible cost: + // - Both 100 wei and 1 wei are almost zero in cost, so this change has no noticeable impact on users. + price := big.NewInt(100) if !oracle.backend.ChainConfig().IsCurie(head.Number) { price = oracle.defaultBasePrice } diff --git a/eth/gasprice/gasprice_test.go b/eth/gasprice/gasprice_test.go index 560b6a69aada..68e028fc4a1a 100644 --- a/eth/gasprice/gasprice_test.go +++ b/eth/gasprice/gasprice_test.go @@ -213,7 +213,7 @@ func TestSuggestTipCap(t *testing.T) { func TestSuggestTipCapCongestedThreshold(t *testing.T) { expectedDefaultBasePricePreCurie := big.NewInt(2000) - expectedDefaultBasePricePostCurie := big.NewInt(1) + expectedDefaultBasePricePostCurie := big.NewInt(100) config := Config{ Blocks: 3, From a8641b2b1be55d6e58904a7e7601c599ed67b0d9 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Thu, 5 Dec 2024 11:41:54 +0000 Subject: [PATCH 02/11] =?UTF-8?q?chore:=20auto=20version=20bump=E2=80=89[b?= =?UTF-8?q?ot]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- params/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/params/version.go b/params/version.go index ede2684a34f7..76862a755adb 100644 --- a/params/version.go +++ b/params/version.go @@ -24,7 +24,7 @@ import ( const ( VersionMajor = 5 // Major version component of the current release VersionMinor = 7 // Minor version component of the current release - VersionPatch = 26 // Patch version component of the current release + VersionPatch = 27 // Patch version component of the current release VersionMeta = "mainnet" // Version metadata to append to the version string ) From d1a249e916bdfe3a32c8a9dfe824a7175f45bd99 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Thu, 5 Dec 2024 22:55:51 +0800 Subject: [PATCH 03/11] make DefaultGasTip configurable --- cmd/utils/flags.go | 7 +++++++ eth/gasprice/gasprice.go | 25 +++++++++++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 3e4ad289a906..2889b11e4027 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -741,6 +741,10 @@ var ( Usage: "Number of pending transactions to consider the network congested and suggest a minimum tip cap", Value: ethconfig.Defaults.GPO.CongestedThreshold, } + GpoDefaultGasTipFlag = cli.Int64Flag{ + Name: "gpo.defaultgastip", + Usage: "Default minimum tip cap (in wei) to be used after Curie fork (EIP-1559)", + } // Metrics flags MetricsEnabledFlag = cli.BoolFlag{ @@ -1450,6 +1454,9 @@ func setGPO(ctx *cli.Context, cfg *gasprice.Config, light bool) { if ctx.GlobalIsSet(GpoCongestionThresholdFlag.Name) { cfg.CongestedThreshold = ctx.GlobalInt(GpoCongestionThresholdFlag.Name) } + if ctx.GlobalIsSet(GpoDefaultGasTipFlag.Name) { + cfg.DefaultGasTip = big.NewInt(ctx.GlobalInt64(GpoDefaultGasTipFlag.Name)) + } } func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) { diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go index f2002d3b871c..eb9c9cd878a7 100644 --- a/eth/gasprice/gasprice.go +++ b/eth/gasprice/gasprice.go @@ -40,6 +40,12 @@ var ( DefaultMaxPrice = big.NewInt(500 * params.GWei) DefaultIgnorePrice = big.NewInt(1 * params.Wei) DefaultBasePrice = big.NewInt(0) + // DefaultGasTip is set to 100 wei instead of 1 wei for the following reasons: + // 1. It prevents issues with very low tip values (e.g., 1 wei): + // - Transaction pools commonly prevent replacing transactions with the same tip cap. + // - Extremely low tips like 1 wei may fail to increase due to rounding in integer arithmetic of SDK implementations (e.g. 1 wei * 1.5 = 1 wei). + // 2. The cost of gas tip 100 wei is negligible compared to base fee normally. + DefaultGasTip = big.NewInt(100) // Default minimum tip cap in wei (used after Curie/EIP-1559). ) type Config struct { @@ -52,6 +58,7 @@ type Config struct { IgnorePrice *big.Int `toml:",omitempty"` CongestedThreshold int // Number of pending transactions to consider the network congested and suggest a minimum tip cap. DefaultBasePrice *big.Int `toml:",omitempty"` // Base price to set when CongestedThreshold is reached before Curie (EIP 1559). + DefaultGasTip *big.Int `toml:",omitempty"` // Default minimum tip cap to use after Curie (EIP 1559). } // OracleBackend includes all necessary background APIs for oracle. @@ -82,6 +89,7 @@ type Oracle struct { maxHeaderHistory, maxBlockHistory int congestedThreshold int // Number of pending transactions to consider the network congested and suggest a minimum tip cap. defaultBasePrice *big.Int // Base price to set when CongestedThreshold is reached before Curie (EIP 1559). + defaultGasTip *big.Int // Default gas tip to suggest when the network is not congested. historyCache *lru.Cache } @@ -133,6 +141,11 @@ func NewOracle(backend OracleBackend, params Config) *Oracle { defaultBasePrice = DefaultBasePrice log.Warn("Sanitizing invalid gasprice oracle default base price", "provided", params.DefaultBasePrice, "updated", defaultBasePrice) } + defaultGasTip := params.DefaultGasTip + if defaultGasTip == nil || defaultGasTip.Int64() < 0 { + defaultGasTip = DefaultGasTip + log.Warn("Sanitizing invalid gasprice oracle default gas tip", "provided", params.DefaultGasTip, "updated", defaultGasTip) + } cache, _ := lru.New(2048) headEvent := make(chan core.ChainHeadEvent, 1) @@ -195,14 +208,10 @@ func (oracle *Oracle) SuggestTipCap(ctx context.Context) (*big.Int, error) { // high-priced txs are causing the suggested tip cap to be high. pendingTxCount, _ := oracle.backend.StatsWithMinBaseFee(head.BaseFee) if pendingTxCount < oracle.congestedThreshold { - // Before Curie (EIP-1559), we need to return the total suggested gas price (base fee + tip cap). - // After Curie, a minimum tip cap of 100 wei is used to avoid issues with extremely low values like 1 wei: - // 1. txpool protections: - // - txpool commonly prevents replacing transactions with the same tip cap. - // - A 1 wei tip may fail to increase (e.g., 1.1x rounds down to 1 wei) due to integer arithmetic. - // 2. Negligible cost: - // - Both 100 wei and 1 wei are almost zero in cost, so this change has no noticeable impact on users. - price := big.NewInt(100) + // Determine the suggested gas price based on the network configuration: + // - Before Curie (EIP-1559): total gas price = base fee + tip cap. + // - After Curie (EIP-1559): use the default tip cap. + price := oracle.defaultGasTip if !oracle.backend.ChainConfig().IsCurie(head.Number) { price = oracle.defaultBasePrice } From 957aa0206a3ccfcff74375ae9efaa24fb940133a Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Thu, 5 Dec 2024 23:02:41 +0800 Subject: [PATCH 04/11] revert a comment change --- eth/gasprice/gasprice.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go index eb9c9cd878a7..cb8c0863cca2 100644 --- a/eth/gasprice/gasprice.go +++ b/eth/gasprice/gasprice.go @@ -208,9 +208,8 @@ func (oracle *Oracle) SuggestTipCap(ctx context.Context) (*big.Int, error) { // high-priced txs are causing the suggested tip cap to be high. pendingTxCount, _ := oracle.backend.StatsWithMinBaseFee(head.BaseFee) if pendingTxCount < oracle.congestedThreshold { - // Determine the suggested gas price based on the network configuration: - // - Before Curie (EIP-1559): total gas price = base fee + tip cap. - // - After Curie (EIP-1559): use the default tip cap. + // Before Curie (EIP-1559), we need to return the total suggested gas price. After Curie we return defaultGasTip wei as the tip cap, + // as the base fee is set separately or added manually for legacy transactions. price := oracle.defaultGasTip if !oracle.backend.ChainConfig().IsCurie(head.Number) { price = oracle.defaultBasePrice From 8082d0ab12a1fda7bc2010bc85c4d9e6e31f4997 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Thu, 5 Dec 2024 23:12:29 +0800 Subject: [PATCH 05/11] fix unit tests --- eth/gasprice/gasprice.go | 1 + 1 file changed, 1 insertion(+) diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go index cb8c0863cca2..82c42becff9e 100644 --- a/eth/gasprice/gasprice.go +++ b/eth/gasprice/gasprice.go @@ -171,6 +171,7 @@ func NewOracle(backend OracleBackend, params Config) *Oracle { maxBlockHistory: maxBlockHistory, congestedThreshold: congestedThreshold, defaultBasePrice: defaultBasePrice, + defaultGasTip: defaultGasTip, historyCache: cache, } } From 81cb6cf780ebd9e261e41574522b6e2cf596e81a Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Thu, 5 Dec 2024 23:23:31 +0800 Subject: [PATCH 06/11] rename GasTip to GasTipCap, more consistent with geth naming conventions --- cmd/utils/flags.go | 10 +++++----- eth/gasprice/gasprice.go | 26 +++++++++++++------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 2889b11e4027..b9b317584930 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -741,9 +741,9 @@ var ( Usage: "Number of pending transactions to consider the network congested and suggest a minimum tip cap", Value: ethconfig.Defaults.GPO.CongestedThreshold, } - GpoDefaultGasTipFlag = cli.Int64Flag{ - Name: "gpo.defaultgastip", - Usage: "Default minimum tip cap (in wei) to be used after Curie fork (EIP-1559)", + GpoDefaultGasTipCapFlag = cli.Int64Flag{ + Name: "gpo.DefaultGasTipCap", + Usage: "Default minimum gas tip cap (in wei) to be used after Curie fork (EIP-1559)", } // Metrics flags @@ -1454,8 +1454,8 @@ func setGPO(ctx *cli.Context, cfg *gasprice.Config, light bool) { if ctx.GlobalIsSet(GpoCongestionThresholdFlag.Name) { cfg.CongestedThreshold = ctx.GlobalInt(GpoCongestionThresholdFlag.Name) } - if ctx.GlobalIsSet(GpoDefaultGasTipFlag.Name) { - cfg.DefaultGasTip = big.NewInt(ctx.GlobalInt64(GpoDefaultGasTipFlag.Name)) + if ctx.GlobalIsSet(GpoDefaultGasTipCapFlag.Name) { + cfg.DefaultGasTipCap = big.NewInt(ctx.GlobalInt64(GpoDefaultGasTipCapFlag.Name)) } } diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go index 82c42becff9e..3f04b4fb0d47 100644 --- a/eth/gasprice/gasprice.go +++ b/eth/gasprice/gasprice.go @@ -40,12 +40,12 @@ var ( DefaultMaxPrice = big.NewInt(500 * params.GWei) DefaultIgnorePrice = big.NewInt(1 * params.Wei) DefaultBasePrice = big.NewInt(0) - // DefaultGasTip is set to 100 wei instead of 1 wei for the following reasons: + // DefaultGasTipCap is set to 100 wei instead of 1 wei for the following reasons: // 1. It prevents issues with very low tip values (e.g., 1 wei): - // - Transaction pools commonly prevent replacing transactions with the same tip cap. + // - Transaction pools commonly prevent replacing transactions with the same gas tip cap. // - Extremely low tips like 1 wei may fail to increase due to rounding in integer arithmetic of SDK implementations (e.g. 1 wei * 1.5 = 1 wei). - // 2. The cost of gas tip 100 wei is negligible compared to base fee normally. - DefaultGasTip = big.NewInt(100) // Default minimum tip cap in wei (used after Curie/EIP-1559). + // 2. The cost of gas tip cap 100 wei is negligible compared to base fee normally. + DefaultGasTipCap = big.NewInt(100) // Default minimum gas tip cap in wei (used after Curie/EIP-1559). ) type Config struct { @@ -58,7 +58,7 @@ type Config struct { IgnorePrice *big.Int `toml:",omitempty"` CongestedThreshold int // Number of pending transactions to consider the network congested and suggest a minimum tip cap. DefaultBasePrice *big.Int `toml:",omitempty"` // Base price to set when CongestedThreshold is reached before Curie (EIP 1559). - DefaultGasTip *big.Int `toml:",omitempty"` // Default minimum tip cap to use after Curie (EIP 1559). + DefaultGasTipCap *big.Int `toml:",omitempty"` // Default minimum gas tip cap to use after Curie (EIP 1559). } // OracleBackend includes all necessary background APIs for oracle. @@ -89,7 +89,7 @@ type Oracle struct { maxHeaderHistory, maxBlockHistory int congestedThreshold int // Number of pending transactions to consider the network congested and suggest a minimum tip cap. defaultBasePrice *big.Int // Base price to set when CongestedThreshold is reached before Curie (EIP 1559). - defaultGasTip *big.Int // Default gas tip to suggest when the network is not congested. + defaultGasTipCap *big.Int // Default gas tip cap to suggest when the network is not congested. historyCache *lru.Cache } @@ -141,10 +141,10 @@ func NewOracle(backend OracleBackend, params Config) *Oracle { defaultBasePrice = DefaultBasePrice log.Warn("Sanitizing invalid gasprice oracle default base price", "provided", params.DefaultBasePrice, "updated", defaultBasePrice) } - defaultGasTip := params.DefaultGasTip - if defaultGasTip == nil || defaultGasTip.Int64() < 0 { - defaultGasTip = DefaultGasTip - log.Warn("Sanitizing invalid gasprice oracle default gas tip", "provided", params.DefaultGasTip, "updated", defaultGasTip) + defaultGasTipCap := params.DefaultGasTipCap + if defaultGasTipCap == nil || defaultGasTipCap.Int64() < 0 { + defaultGasTipCap = DefaultGasTipCap + log.Warn("Sanitizing invalid gasprice oracle default gas tip cap", "provided", params.DefaultGasTipCap, "updated", DefaultGasTipCap) } cache, _ := lru.New(2048) @@ -171,7 +171,7 @@ func NewOracle(backend OracleBackend, params Config) *Oracle { maxBlockHistory: maxBlockHistory, congestedThreshold: congestedThreshold, defaultBasePrice: defaultBasePrice, - defaultGasTip: defaultGasTip, + defaultGasTipCap: defaultGasTipCap, historyCache: cache, } } @@ -209,9 +209,9 @@ func (oracle *Oracle) SuggestTipCap(ctx context.Context) (*big.Int, error) { // high-priced txs are causing the suggested tip cap to be high. pendingTxCount, _ := oracle.backend.StatsWithMinBaseFee(head.BaseFee) if pendingTxCount < oracle.congestedThreshold { - // Before Curie (EIP-1559), we need to return the total suggested gas price. After Curie we return defaultGasTip wei as the tip cap, + // Before Curie (EIP-1559), we need to return the total suggested gas price. After Curie we return defaultGasTipCap wei as the tip cap, // as the base fee is set separately or added manually for legacy transactions. - price := oracle.defaultGasTip + price := oracle.defaultGasTipCap if !oracle.backend.ChainConfig().IsCurie(head.Number) { price = oracle.defaultBasePrice } From eb7739b5b93d606a9b6ddb627fe8c0f9b77a4b88 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Fri, 6 Dec 2024 02:00:24 +0800 Subject: [PATCH 07/11] yet another comment tweak --- eth/gasprice/gasprice.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go index 3f04b4fb0d47..455f62703ffc 100644 --- a/eth/gasprice/gasprice.go +++ b/eth/gasprice/gasprice.go @@ -41,10 +41,10 @@ var ( DefaultIgnorePrice = big.NewInt(1 * params.Wei) DefaultBasePrice = big.NewInt(0) // DefaultGasTipCap is set to 100 wei instead of 1 wei for the following reasons: - // 1. It prevents issues with very low tip values (e.g., 1 wei): - // - Transaction pools commonly prevent replacing transactions with the same gas tip cap. - // - Extremely low tips like 1 wei may fail to increase due to rounding in integer arithmetic of SDK implementations (e.g. 1 wei * 1.5 = 1 wei). - // 2. The cost of gas tip cap 100 wei is negligible compared to base fee normally. + // 1. Very low tip values (e.g. 1 wei) can cause issues because transaction pools often reject replacing transactions + // with the same gas tip cap. This becomes problematic when low tips like 1 wei fail to increase due to rounding + // in some SDK implementations (e.g. 1 wei * 1.5 = 1 wei). + // 2. The cost of a gas tip cap of 100 wei is negligible compared to the base fee in most cases. DefaultGasTipCap = big.NewInt(100) // Default minimum gas tip cap in wei (used after Curie/EIP-1559). ) From 272f9fc8858263dcdf513747a55f7ddfe1682e7c Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Fri, 6 Dec 2024 02:01:58 +0800 Subject: [PATCH 08/11] tweak --- eth/gasprice/gasprice.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go index 455f62703ffc..766df61d4422 100644 --- a/eth/gasprice/gasprice.go +++ b/eth/gasprice/gasprice.go @@ -89,7 +89,7 @@ type Oracle struct { maxHeaderHistory, maxBlockHistory int congestedThreshold int // Number of pending transactions to consider the network congested and suggest a minimum tip cap. defaultBasePrice *big.Int // Base price to set when CongestedThreshold is reached before Curie (EIP 1559). - defaultGasTipCap *big.Int // Default gas tip cap to suggest when the network is not congested. + defaultGasTipCap *big.Int // Default gas tip cap to suggest after Curie (EIP 1559) when the network is not congested. historyCache *lru.Cache } From 8d8cb44dc15f4ccc2071e1cb525c25352d645cdb Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Fri, 6 Dec 2024 03:15:28 +0800 Subject: [PATCH 09/11] address comments --- cmd/utils/flags.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index b9b317584930..88cd0dbd18ea 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -742,7 +742,7 @@ var ( Value: ethconfig.Defaults.GPO.CongestedThreshold, } GpoDefaultGasTipCapFlag = cli.Int64Flag{ - Name: "gpo.DefaultGasTipCap", + Name: "gpo.defaultgastipcap", Usage: "Default minimum gas tip cap (in wei) to be used after Curie fork (EIP-1559)", } From 30fdcd5b77b1e325f20442a2aa4d387a1c9e7cb1 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Fri, 6 Dec 2024 03:16:24 +0800 Subject: [PATCH 10/11] another --- cmd/utils/flags.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 88cd0dbd18ea..07f055a4e12f 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -743,7 +743,7 @@ var ( } GpoDefaultGasTipCapFlag = cli.Int64Flag{ Name: "gpo.defaultgastipcap", - Usage: "Default minimum gas tip cap (in wei) to be used after Curie fork (EIP-1559)", + Usage: "Default minimum gas tip cap (in wei) to be used after Curie fork (EIP-1559) (default: 100)", } // Metrics flags From 5e3cbb30f8e1ae9885b5df8be63807b2d85cefdb Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Fri, 6 Dec 2024 17:53:41 +0800 Subject: [PATCH 11/11] make defaultGasTipCap.Int64 >0 --- eth/gasprice/gasprice.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go index 766df61d4422..a5897433e512 100644 --- a/eth/gasprice/gasprice.go +++ b/eth/gasprice/gasprice.go @@ -142,7 +142,7 @@ func NewOracle(backend OracleBackend, params Config) *Oracle { log.Warn("Sanitizing invalid gasprice oracle default base price", "provided", params.DefaultBasePrice, "updated", defaultBasePrice) } defaultGasTipCap := params.DefaultGasTipCap - if defaultGasTipCap == nil || defaultGasTipCap.Int64() < 0 { + if defaultGasTipCap == nil || defaultGasTipCap.Int64() <= 0 { defaultGasTipCap = DefaultGasTipCap log.Warn("Sanitizing invalid gasprice oracle default gas tip cap", "provided", params.DefaultGasTipCap, "updated", DefaultGasTipCap) }