From e235a31d4cc0f3b817c5c8ab3ca13d6a1c8b7e73 Mon Sep 17 00:00:00 2001 From: blockchaindevsh Date: Mon, 7 Jul 2025 23:05:43 +0800 Subject: [PATCH] cgt --- core/types/rollup_cost.go | 14 +++++++++++--- core/types/rollup_cost_test.go | 32 ++++++++++++++++++++++++++++++++ eth/ethconfig/config.go | 2 +- eth/gasprice/gasprice.go | 2 +- params/config.go | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 5 deletions(-) diff --git a/core/types/rollup_cost.go b/core/types/rollup_cost.go index 68db0a1188..8a3b96ac1e 100644 --- a/core/types/rollup_cost.go +++ b/core/types/rollup_cost.go @@ -174,11 +174,14 @@ func NewL1CostFunc(config *params.ChainConfig, statedb StateGetter) L1CostFunc { l1BaseFeeScalar, l1BlobBaseFeeScalar := ExtractEcotoneFeeParams(l1FeeScalars) if config.IsOptimismFjord(blockTime) { + l1BaseFeeScalarMultiplier, l1BlobBaseFeeScalarMultiplier := config.Optimism.L1ScalarMultipliers(blockTime) return NewL1CostFuncFjord( l1BaseFee, l1BlobBaseFee, l1BaseFeeScalar, l1BlobBaseFeeScalar, + l1BaseFeeScalarMultiplier, + l1BlobBaseFeeScalarMultiplier, ) } else { return newL1CostFuncEcotone(l1BaseFee, l1BlobBaseFee, l1BaseFeeScalar, l1BlobBaseFeeScalar) @@ -378,6 +381,8 @@ func intToScaledFloat(scalar *big.Int) *big.Float { // extractL1GasParams extracts the gas parameters necessary to compute gas costs from L1 block info func extractL1GasParams(config *params.ChainConfig, time uint64, data []byte) (gasParams, error) { + l1BaseFeeScalarMultiplier, l1BlobBaseFeeScalarMultiplier := config.Optimism.L1ScalarMultipliers(time) + if config.IsIsthmus(time) && len(data) >= 4 && !bytes.Equal(data[0:4], EcotoneL1AttributesSelector) { // edge case: for the very first Isthmus block we still need to use the Ecotone // function. We detect this edge case by seeing if the function selector is the old one @@ -386,11 +391,13 @@ func extractL1GasParams(config *params.ChainConfig, time uint64, data []byte) (g if err != nil { return gasParams{}, err } + p.costFunc = NewL1CostFuncFjord( p.l1BaseFee, p.l1BlobBaseFee, big.NewInt(int64(*p.l1BaseFeeScalar)), big.NewInt(int64(*p.l1BlobBaseFeeScalar)), + l1BaseFeeScalarMultiplier, l1BlobBaseFeeScalarMultiplier, ) return p, nil } else if config.IsEcotone(time) && len(data) >= 4 && !bytes.Equal(data[0:4], BedrockL1AttributesSelector) { @@ -409,6 +416,7 @@ func extractL1GasParams(config *params.ChainConfig, time uint64, data []byte) (g p.l1BlobBaseFee, big.NewInt(int64(*p.l1BaseFeeScalar)), big.NewInt(int64(*p.l1BlobBaseFeeScalar)), + l1BaseFeeScalarMultiplier, l1BlobBaseFeeScalarMultiplier, ) } else { p.costFunc = newL1CostFuncEcotone( @@ -524,16 +532,16 @@ func l1CostHelper(gasWithOverhead, l1BaseFee, scalar *big.Int) *big.Int { } // NewL1CostFuncFjord returns an l1 cost function suitable for the Fjord upgrade -func NewL1CostFuncFjord(l1BaseFee, l1BlobBaseFee, baseFeeScalar, blobFeeScalar *big.Int) l1CostFunc { +func NewL1CostFuncFjord(l1BaseFee, l1BlobBaseFee, baseFeeScalar, blobFeeScalar, l1BaseFeeScalarMultiplier, l1BlobBaseFeeScalarMultiplier *big.Int) l1CostFunc { return func(costData RollupCostData) (fee, calldataGasUsed *big.Int) { // Fjord L1 cost function: // l1FeeScaled = baseFeeScalar*l1BaseFee*16 + blobFeeScalar*l1BlobBaseFee // estimatedSize = max(minTransactionSize, intercept + fastlzCoef*fastlzSize) // l1Cost = estimatedSize * l1FeeScaled / 1e12 - scaledL1BaseFee := new(big.Int).Mul(baseFeeScalar, l1BaseFee) + scaledL1BaseFee := new(big.Int).Mul(new(big.Int).Mul(baseFeeScalar, l1BaseFeeScalarMultiplier), l1BaseFee) calldataCostPerByte := new(big.Int).Mul(scaledL1BaseFee, sixteen) - blobCostPerByte := new(big.Int).Mul(blobFeeScalar, l1BlobBaseFee) + blobCostPerByte := new(big.Int).Mul(new(big.Int).Mul(blobFeeScalar, l1BlobBaseFeeScalarMultiplier), l1BlobBaseFee) l1FeeScaled := new(big.Int).Add(calldataCostPerByte, blobCostPerByte) estimatedSize := costData.estimatedDASizeScaled() l1CostScaled := new(big.Int).Mul(estimatedSize, l1FeeScaled) diff --git a/core/types/rollup_cost_test.go b/core/types/rollup_cost_test.go index b595a14f62..0075c2540b 100644 --- a/core/types/rollup_cost_test.go +++ b/core/types/rollup_cost_test.go @@ -7,6 +7,8 @@ import ( "math/big" "testing" + math2 "math" + "github.com/holiman/uint256" "github.com/stretchr/testify/require" @@ -69,6 +71,8 @@ func TestFjordL1CostFuncMinimumBounds(t *testing.T) { blobBaseFee, baseFeeScalar, blobBaseFeeScalar, + big.NewInt(1), + big.NewInt(1), ) // Minimum size transactions: @@ -106,6 +110,8 @@ func TestFjordL1CostSolidityParity(t *testing.T) { big.NewInt(3*1e6), big.NewInt(20), big.NewInt(15), + big.NewInt(1), + big.NewInt(1), ) c0, g0 := costFunc(RollupCostData{ @@ -355,6 +361,32 @@ func (sg *testStateGetter) GetState(addr common.Address, slot common.Hash) commo return buf } +// This test checks that the L1 scalar multipliers are used in NewL1CostFunc +// for latest HF, but still need to manually check the usage in extractL1GasParams. +// it's best-effort only. +func TestL1ScalarMultipliersAreUsedInLatestHF(t *testing.T) { + + // Note: may still need to manually turn on the latest HF flag if OP hasn't do that yet + config := params.OptimismTestConfig + statedb := &testStateGetter{ + baseFee: baseFee, + overhead: overhead, + scalar: scalar, + blobBaseFee: blobBaseFee, + baseFeeScalar: uint32(baseFeeScalar.Uint64()), + blobBaseFeeScalar: uint32(blobBaseFeeScalar.Uint64()), + } + + params.L1ScalarMultipliersCalled = false + params.L1ScalarMultipliersTestFlag = true + costFunc := NewL1CostFunc(config, statedb) + require.NotNil(t, costFunc) + + costFunc(emptyTx.RollupCostData(), math2.MaxUint64-1 /*math2.MaxUint64 is used as a special mark in NewL1CostFunc, so minus 1*/) + + require.Equal(t, params.L1ScalarMultipliersCalled, true) +} + // TestNewL1CostFunc tests that the appropriate cost function is selected based on the // configuration and statedb values. func TestNewL1CostFunc(t *testing.T) { diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index d12fb00f2f..a4bbcc49b5 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -69,7 +69,7 @@ var Defaults = Config{ RPCGasCap: 50000000, RPCEVMTimeout: 5 * time.Second, GPO: FullNodeGPO, - RPCTxFeeCap: 1, // 1 ether + RPCTxFeeCap: 1000, // 1000 QKC } //go:generate go run github.com/fjl/gencodec -type Config -formats toml -out gen_config.go diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go index 58a59cbdb9..5f8776a722 100644 --- a/eth/gasprice/gasprice.go +++ b/eth/gasprice/gasprice.go @@ -39,7 +39,7 @@ var ( DefaultMaxPrice = big.NewInt(500 * params.GWei) DefaultIgnorePrice = big.NewInt(2 * params.Wei) - DefaultMinSuggestedPriorityFee = big.NewInt(1e6 * params.Wei) // 0.001 gwei, for Optimism fee suggestion + DefaultMinSuggestedPriorityFee = big.NewInt(1e9 * params.Wei) // 1 gwei, for Optimism fee suggestion ) type Config struct { diff --git a/params/config.go b/params/config.go index c517953400..567cb76c94 100644 --- a/params/config.go +++ b/params/config.go @@ -511,6 +511,12 @@ type OptimismConfig struct { EIP1559Elasticity uint64 `json:"eip1559Elasticity"` EIP1559Denominator uint64 `json:"eip1559Denominator"` EIP1559DenominatorCanyon *uint64 `json:"eip1559DenominatorCanyon,omitempty"` + // The multiplier of the L1BaseFeeScalar, used to keep the L1BaseFeeScalar size compatible with uint32 and calculate the effective L1BaseFeeScalar; + // Only effective when the value is non-zero + L1BaseFeeScalarMultiplier uint64 `json:"l1BaseFeeScalarMultiplier,omitempty"` + // The multiplier of the L1BlobBaseFeeScalar, used to keep the L1BlobBaseFeeScalar size compatible with uint32 and calculate the effective L1BlobBaseFeeScalar; + // Only effective when the value is non-zero + L1BlobBaseFeeScalarMultiplier uint64 `json:"l1BlobBaseFeeScalarMultiplier,omitempty"` } // String implements the stringer interface, returning the optimism fee config details. @@ -518,6 +524,33 @@ func (o *OptimismConfig) String() string { return "optimism" } +// this flag is only true in test +var L1ScalarMultipliersTestFlag bool +var L1ScalarMultipliersCalled bool + +// L1ScalarMultipliers returns the scalar multipliers to make the L1BaseFeeScalar and L1BlobBaseFeeScalar compatible with uint32. +// It needs to be applied for all future changes to the L1 cost. +func (o *OptimismConfig) L1ScalarMultipliers(blockTime uint64) (*big.Int, *big.Int) { + // blockTime is not used in the current implementation, but it is kept here for future compatibility + + // this code block is only used for test + if L1ScalarMultipliersTestFlag && !L1ScalarMultipliersCalled { + L1ScalarMultipliersCalled = true + } + + // default values for the scalar multipliers + l1BaseFeeScalarMultiplier := int64(1) + l1BlobBaseFeeScalarMultiplier := int64(1) + + if o.L1BaseFeeScalarMultiplier != 0 { + l1BaseFeeScalarMultiplier = int64(o.L1BaseFeeScalarMultiplier) + } + if o.L1BlobBaseFeeScalarMultiplier != 0 { + l1BlobBaseFeeScalarMultiplier = int64(o.L1BlobBaseFeeScalarMultiplier) + } + return big.NewInt(l1BaseFeeScalarMultiplier), big.NewInt(l1BlobBaseFeeScalarMultiplier) +} + // Description returns a human-readable description of ChainConfig. func (c *ChainConfig) Description() string { var banner string