From 3d50dd154f8f463edf886c645fa7ddff8a7f7e88 Mon Sep 17 00:00:00 2001 From: Alejandro Ranchal-Pedrosa Date: Sat, 7 Jun 2025 11:50:53 +0200 Subject: [PATCH 01/23] Change l1DataFee to rollupFee for Feynman --- params/config.go | 5 +++++ rollup/fees/rollup_fee.go | 42 +++++++++++++++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/params/config.go b/params/config.go index 96b77e04a7f4..34888d5f66c9 100644 --- a/params/config.go +++ b/params/config.go @@ -988,6 +988,11 @@ func (c *ChainConfig) IsEuclidV2(now uint64) bool { return isForkedTime(now, c.EuclidV2Time) } +// IsFeynman returns whether num is either equal to the Feynman fork block or greater. +func (c *ChainConfig) IsFeynman(num *big.Int) bool { + return false // placeholder +} + // IsTerminalPoWBlock returns whether the given block is the last block of PoW stage. func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *big.Int) bool { if c.TerminalTotalDifficulty == nil { diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index 2c46aeedbfad..a52b737ad95e 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -51,7 +51,7 @@ type gpoState struct { overhead *big.Int scalar *big.Int l1BlobBaseFee *big.Int - commitScalar *big.Int + execScalar *big.Int blobScalar *big.Int } @@ -78,8 +78,10 @@ func EstimateL1DataFeeForMessage(msg Message, baseFee *big.Int, config *params.C if !config.IsCurie(blockNumber) { l1DataFee = calculateEncodedL1DataFee(raw, gpoState.overhead, gpoState.l1BaseFee, gpoState.scalar) + } else if !config.IsFeynman(blockNumber) { + l1DataFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.execScalar, gpoState.blobScalar) } else { - l1DataFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) + l1DataFee = calculateEncodedL1DataFeeFeynman(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.execScalar, gpoState.blobScalar) } return l1DataFee, nil @@ -164,7 +166,7 @@ func readGPOStorageSlots(addr common.Address, state StateDB) gpoState { gpoState.overhead = state.GetState(addr, rcfg.OverheadSlot).Big() gpoState.scalar = state.GetState(addr, rcfg.ScalarSlot).Big() gpoState.l1BlobBaseFee = state.GetState(addr, rcfg.L1BlobBaseFeeSlot).Big() - gpoState.commitScalar = state.GetState(addr, rcfg.CommitScalarSlot).Big() + gpoState.execScalar = state.GetState(addr, rcfg.CommitScalarSlot).Big() gpoState.blobScalar = state.GetState(addr, rcfg.BlobScalarSlot).Big() return gpoState } @@ -193,6 +195,36 @@ func calculateEncodedL1DataFeeCurie(data []byte, l1BaseFee *big.Int, l1BlobBaseF return l1DataFee } +// calculateEncodedL1DataFeeFeynman computes the L1 fee for an RLP-encoded tx, post Feynman +func calculateEncodedL1DataFeeFeynman( + data []byte, + l1BaseFee *big.Int, + l1BlobBaseFee *big.Int, + execScalar *big.Int, + blobScalar *big.Int, +) *big.Int { + // tx size (RLP-encoded) + txSize := big.NewInt(int64(len(data))) + + // compression_ratio(tx) = 1 (placeholder) + compressionRatio := big.NewInt(1) + + // compute gas components + execGas := new(big.Int).Mul(execScalar, l1BaseFee) + blobGas := new(big.Int).Mul(blobScalar, l1BlobBaseFee) + + // fee per byte = execGas + blobGas + feePerByte := new(big.Int).Add(execGas, blobGas) + + // fee = compression_ratio * tx_size * (execGas + blobGas) + rollupFee := new(big.Int).Mul(compressionRatio, txSize) + rollupFee.Mul(rollupFee, feePerByte) + + rollupFee = new(big.Int).Quo(rollupFee, rcfg.Precision) + + return rollupFee +} + // calculateL1GasUsed computes the L1 gas used based on the calldata and // constant sized overhead. The overhead can be decreased as the cost of the // batch submission goes down via contract optimizations. This will not overflow @@ -242,8 +274,10 @@ func CalculateL1DataFee(tx *types.Transaction, state StateDB, config *params.Cha if !config.IsCurie(blockNumber) { l1DataFee = calculateEncodedL1DataFee(raw, gpoState.overhead, gpoState.l1BaseFee, gpoState.scalar) + } else if !config.IsFeynman(blockNumber) { + l1DataFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.execScalar, gpoState.blobScalar) } else { - l1DataFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) + l1DataFee = calculateEncodedL1DataFeeFeynman(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.execScalar, gpoState.blobScalar) } // ensure l1DataFee fits into uint64 for circuit compatibility From 98f41d758394ad60dfde12335b1a9af97e8c0963 Mon Sep 17 00:00:00 2001 From: Alejandro Ranchal-Pedrosa Date: Sat, 7 Jun 2025 12:01:29 +0200 Subject: [PATCH 02/23] Update CommitScalarSlot to ExecScalarSlot --- consensus/misc/curie.go | 2 +- core/blockchain_test.go | 2 +- ethclient/ethclient_test.go | 2 +- ethclient/gethclient/gethclient_test.go | 2 +- rollup/fees/rollup_fee.go | 2 +- rollup/rcfg/config.go | 2 +- rollup/tracing/tracing.go | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/consensus/misc/curie.go b/consensus/misc/curie.go index e1668b25dc33..77b004d68121 100644 --- a/consensus/misc/curie.go +++ b/consensus/misc/curie.go @@ -18,6 +18,6 @@ func ApplyCurieHardFork(statedb *state.StateDB) { // initialize new storage slots statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.IsCurieSlot, common.BytesToHash([]byte{1})) statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.L1BlobBaseFeeSlot, common.BytesToHash([]byte{1})) - statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.CommitScalarSlot, common.BigToHash(rcfg.InitialCommitScalar)) + statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.ExecScalarSlot, common.BigToHash(rcfg.InitialCommitScalar)) statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.BlobScalarSlot, common.BigToHash(rcfg.InitialBlobScalar)) } diff --git a/core/blockchain_test.go b/core/blockchain_test.go index febdb032ac13..7ba0b126df31 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -3757,7 +3757,7 @@ func TestCurieTransition(t *testing.T) { poseidonCodeHash := statedb.GetPoseidonCodeHash(rcfg.L1GasPriceOracleAddress) l1BlobBaseFee := statedb.GetState(rcfg.L1GasPriceOracleAddress, rcfg.L1BlobBaseFeeSlot) - commitScalar := statedb.GetState(rcfg.L1GasPriceOracleAddress, rcfg.CommitScalarSlot) + commitScalar := statedb.GetState(rcfg.L1GasPriceOracleAddress, rcfg.ExecScalarSlot) blobScalar := statedb.GetState(rcfg.L1GasPriceOracleAddress, rcfg.BlobScalarSlot) isCurie := statedb.GetState(rcfg.L1GasPriceOracleAddress, rcfg.IsCurieSlot) diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go index 6e1e1393d6b6..e27f5ee19b9b 100644 --- a/ethclient/ethclient_test.go +++ b/ethclient/ethclient_test.go @@ -201,7 +201,7 @@ var genesis = &core.Genesis{ rcfg.OverheadSlot: common.BigToHash(big.NewInt(10000)), rcfg.ScalarSlot: common.BigToHash(big.NewInt(10000)), rcfg.L1BlobBaseFeeSlot: common.BigToHash(big.NewInt(10000)), - rcfg.CommitScalarSlot: common.BigToHash(big.NewInt(10000)), + rcfg.ExecScalarSlot: common.BigToHash(big.NewInt(10000)), rcfg.BlobScalarSlot: common.BigToHash(big.NewInt(10000)), rcfg.IsCurieSlot: common.BytesToHash([]byte{1}), }, diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index 32f16e8c035b..bf0ccb311433 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -85,7 +85,7 @@ func generateTestChain() (*core.Genesis, []*types.Block) { rcfg.OverheadSlot: common.BigToHash(big.NewInt(10000)), rcfg.ScalarSlot: common.BigToHash(big.NewInt(10000)), rcfg.L1BlobBaseFeeSlot: common.BigToHash(big.NewInt(10000)), - rcfg.CommitScalarSlot: common.BigToHash(big.NewInt(10000)), + rcfg.ExecScalarSlot: common.BigToHash(big.NewInt(10000)), rcfg.BlobScalarSlot: common.BigToHash(big.NewInt(10000)), rcfg.IsCurieSlot: common.BytesToHash([]byte{1}), }, diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index a52b737ad95e..05cb87a44ba8 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -166,7 +166,7 @@ func readGPOStorageSlots(addr common.Address, state StateDB) gpoState { gpoState.overhead = state.GetState(addr, rcfg.OverheadSlot).Big() gpoState.scalar = state.GetState(addr, rcfg.ScalarSlot).Big() gpoState.l1BlobBaseFee = state.GetState(addr, rcfg.L1BlobBaseFeeSlot).Big() - gpoState.execScalar = state.GetState(addr, rcfg.CommitScalarSlot).Big() + gpoState.execScalar = state.GetState(addr, rcfg.ExecScalarSlot).Big() gpoState.blobScalar = state.GetState(addr, rcfg.BlobScalarSlot).Big() return gpoState } diff --git a/rollup/rcfg/config.go b/rollup/rcfg/config.go index 3bac185c8302..bc692a88383a 100644 --- a/rollup/rcfg/config.go +++ b/rollup/rcfg/config.go @@ -32,7 +32,7 @@ var ( // New fields added in the Curie hard fork L1BlobBaseFeeSlot = common.BigToHash(big.NewInt(5)) - CommitScalarSlot = common.BigToHash(big.NewInt(6)) + ExecScalarSlot = common.BigToHash(big.NewInt(6)) BlobScalarSlot = common.BigToHash(big.NewInt(7)) IsCurieSlot = common.BigToHash(big.NewInt(8)) diff --git a/rollup/tracing/tracing.go b/rollup/tracing/tracing.go index 86fe1381c0e8..88d8b3110872 100644 --- a/rollup/tracing/tracing.go +++ b/rollup/tracing/tracing.go @@ -543,7 +543,7 @@ func (env *TraceEnv) fillBlockTrace(block *types.Block) (*types.BlockTrace, erro rcfg.OverheadSlot, rcfg.ScalarSlot, rcfg.L1BlobBaseFeeSlot, - rcfg.CommitScalarSlot, + rcfg.ExecScalarSlot, rcfg.BlobScalarSlot, rcfg.IsCurieSlot, }, From 90bd9f4baf60bbbc53f2fc1b58d21cf05f4015c1 Mon Sep 17 00:00:00 2001 From: Alejandro Ranchal-Pedrosa Date: Mon, 9 Jun 2025 10:26:03 +0200 Subject: [PATCH 03/23] Rename l1DataFee to rollupFee --- rollup/fees/rollup_fee.go | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index 05cb87a44ba8..289fb4503824 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -74,17 +74,17 @@ func EstimateL1DataFeeForMessage(msg Message, baseFee *big.Int, config *params.C gpoState := readGPOStorageSlots(rcfg.L1GasPriceOracleAddress, state) - var l1DataFee *big.Int + var rollupFee *big.Int if !config.IsCurie(blockNumber) { - l1DataFee = calculateEncodedL1DataFee(raw, gpoState.overhead, gpoState.l1BaseFee, gpoState.scalar) + rollupFee = calculateEncodedL1DataFee(raw, gpoState.overhead, gpoState.l1BaseFee, gpoState.scalar) } else if !config.IsFeynman(blockNumber) { - l1DataFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.execScalar, gpoState.blobScalar) + rollupFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.execScalar, gpoState.blobScalar) } else { - l1DataFee = calculateEncodedL1DataFeeFeynman(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.execScalar, gpoState.blobScalar) + rollupFee = calculateEncodedRollupFeeFeeFeynman(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.execScalar, gpoState.blobScalar) } - return l1DataFee, nil + return rollupFee, nil } // asUnsignedTx turns a Message into a types.Transaction @@ -195,8 +195,8 @@ func calculateEncodedL1DataFeeCurie(data []byte, l1BaseFee *big.Int, l1BlobBaseF return l1DataFee } -// calculateEncodedL1DataFeeFeynman computes the L1 fee for an RLP-encoded tx, post Feynman -func calculateEncodedL1DataFeeFeynman( +// calculateEncodedRollupFeeFeeFeynman computes the L1 fee for an RLP-encoded tx, post Feynman +func calculateEncodedRollupFeeFeeFeynman( data []byte, l1BaseFee *big.Int, l1BlobBaseFee *big.Int, @@ -270,23 +270,23 @@ func CalculateL1DataFee(tx *types.Transaction, state StateDB, config *params.Cha gpoState := readGPOStorageSlots(rcfg.L1GasPriceOracleAddress, state) - var l1DataFee *big.Int + var rollupFee *big.Int if !config.IsCurie(blockNumber) { - l1DataFee = calculateEncodedL1DataFee(raw, gpoState.overhead, gpoState.l1BaseFee, gpoState.scalar) + rollupFee = calculateEncodedL1DataFee(raw, gpoState.overhead, gpoState.l1BaseFee, gpoState.scalar) } else if !config.IsFeynman(blockNumber) { - l1DataFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.execScalar, gpoState.blobScalar) + rollupFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.execScalar, gpoState.blobScalar) } else { - l1DataFee = calculateEncodedL1DataFeeFeynman(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.execScalar, gpoState.blobScalar) + rollupFee = calculateEncodedRollupFeeFeeFeynman(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.execScalar, gpoState.blobScalar) } - // ensure l1DataFee fits into uint64 for circuit compatibility + // ensure rollupFee fits into uint64 for circuit compatibility // (note: in practice this value should never be this big) - if !l1DataFee.IsUint64() { - l1DataFee.SetUint64(math.MaxUint64) + if !rollupFee.IsUint64() { + rollupFee.SetUint64(math.MaxUint64) } - return l1DataFee, nil + return rollupFee, nil } func GetL1BaseFee(state StateDB) *big.Int { From 49574cbcf5d32132cbdbac849a982a79af365e22 Mon Sep 17 00:00:00 2001 From: Alejandro Ranchal-Pedrosa Date: Mon, 9 Jun 2025 12:17:38 +0200 Subject: [PATCH 04/23] Scale compression ratio to match scalars precision --- rollup/fees/rollup_fee.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index 289fb4503824..8384bbd1af34 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -206,8 +206,8 @@ func calculateEncodedRollupFeeFeeFeynman( // tx size (RLP-encoded) txSize := big.NewInt(int64(len(data))) - // compression_ratio(tx) = 1 (placeholder) - compressionRatio := big.NewInt(1) + // compression_ratio(tx) = 1 (placeholder, scaled to match scalars precision) + compressionRatio := big.NewInt(rcfg.Precision.Int64()) // compute gas components execGas := new(big.Int).Mul(execScalar, l1BaseFee) @@ -216,11 +216,13 @@ func calculateEncodedRollupFeeFeeFeynman( // fee per byte = execGas + blobGas feePerByte := new(big.Int).Add(execGas, blobGas) - // fee = compression_ratio * tx_size * (execGas + blobGas) + // rollupFee = compression_ratio * tx_size * feePerByte rollupFee := new(big.Int).Mul(compressionRatio, txSize) rollupFee.Mul(rollupFee, feePerByte) - rollupFee = new(big.Int).Quo(rollupFee, rcfg.Precision) + // Divide by rcfg.Precision (once for ratio, once for scalar) + rollupFee.Div(rollupFee, rcfg.Precision) + rollupFee.Div(rollupFee, rcfg.Precision) return rollupFee } From 685e4bafc86aaf23cdf08b075adeae0105d60dc6 Mon Sep 17 00:00:00 2001 From: Alejandro Ranchal-Pedrosa Date: Tue, 10 Jun 2025 22:16:26 +0200 Subject: [PATCH 05/23] Use l1DataFee and commitScalar instead of rollupFee and execScalar --- consensus/misc/curie.go | 2 +- core/blockchain_test.go | 2 +- ethclient/ethclient_test.go | 2 +- ethclient/gethclient/gethclient_test.go | 2 +- rollup/fees/rollup_fee.go | 40 ++++++++++++------------- rollup/rcfg/config.go | 2 +- rollup/tracing/tracing.go | 2 +- 7 files changed, 26 insertions(+), 26 deletions(-) diff --git a/consensus/misc/curie.go b/consensus/misc/curie.go index 77b004d68121..e1668b25dc33 100644 --- a/consensus/misc/curie.go +++ b/consensus/misc/curie.go @@ -18,6 +18,6 @@ func ApplyCurieHardFork(statedb *state.StateDB) { // initialize new storage slots statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.IsCurieSlot, common.BytesToHash([]byte{1})) statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.L1BlobBaseFeeSlot, common.BytesToHash([]byte{1})) - statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.ExecScalarSlot, common.BigToHash(rcfg.InitialCommitScalar)) + statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.CommitScalarSlot, common.BigToHash(rcfg.InitialCommitScalar)) statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.BlobScalarSlot, common.BigToHash(rcfg.InitialBlobScalar)) } diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 7ba0b126df31..febdb032ac13 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -3757,7 +3757,7 @@ func TestCurieTransition(t *testing.T) { poseidonCodeHash := statedb.GetPoseidonCodeHash(rcfg.L1GasPriceOracleAddress) l1BlobBaseFee := statedb.GetState(rcfg.L1GasPriceOracleAddress, rcfg.L1BlobBaseFeeSlot) - commitScalar := statedb.GetState(rcfg.L1GasPriceOracleAddress, rcfg.ExecScalarSlot) + commitScalar := statedb.GetState(rcfg.L1GasPriceOracleAddress, rcfg.CommitScalarSlot) blobScalar := statedb.GetState(rcfg.L1GasPriceOracleAddress, rcfg.BlobScalarSlot) isCurie := statedb.GetState(rcfg.L1GasPriceOracleAddress, rcfg.IsCurieSlot) diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go index e27f5ee19b9b..6e1e1393d6b6 100644 --- a/ethclient/ethclient_test.go +++ b/ethclient/ethclient_test.go @@ -201,7 +201,7 @@ var genesis = &core.Genesis{ rcfg.OverheadSlot: common.BigToHash(big.NewInt(10000)), rcfg.ScalarSlot: common.BigToHash(big.NewInt(10000)), rcfg.L1BlobBaseFeeSlot: common.BigToHash(big.NewInt(10000)), - rcfg.ExecScalarSlot: common.BigToHash(big.NewInt(10000)), + rcfg.CommitScalarSlot: common.BigToHash(big.NewInt(10000)), rcfg.BlobScalarSlot: common.BigToHash(big.NewInt(10000)), rcfg.IsCurieSlot: common.BytesToHash([]byte{1}), }, diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index bf0ccb311433..32f16e8c035b 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -85,7 +85,7 @@ func generateTestChain() (*core.Genesis, []*types.Block) { rcfg.OverheadSlot: common.BigToHash(big.NewInt(10000)), rcfg.ScalarSlot: common.BigToHash(big.NewInt(10000)), rcfg.L1BlobBaseFeeSlot: common.BigToHash(big.NewInt(10000)), - rcfg.ExecScalarSlot: common.BigToHash(big.NewInt(10000)), + rcfg.CommitScalarSlot: common.BigToHash(big.NewInt(10000)), rcfg.BlobScalarSlot: common.BigToHash(big.NewInt(10000)), rcfg.IsCurieSlot: common.BytesToHash([]byte{1}), }, diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index 8384bbd1af34..5a4390d79a5f 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -51,7 +51,7 @@ type gpoState struct { overhead *big.Int scalar *big.Int l1BlobBaseFee *big.Int - execScalar *big.Int + commitScalar *big.Int blobScalar *big.Int } @@ -79,9 +79,9 @@ func EstimateL1DataFeeForMessage(msg Message, baseFee *big.Int, config *params.C if !config.IsCurie(blockNumber) { rollupFee = calculateEncodedL1DataFee(raw, gpoState.overhead, gpoState.l1BaseFee, gpoState.scalar) } else if !config.IsFeynman(blockNumber) { - rollupFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.execScalar, gpoState.blobScalar) + rollupFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) } else { - rollupFee = calculateEncodedRollupFeeFeeFeynman(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.execScalar, gpoState.blobScalar) + rollupFee = calculateEncodedL1DataFeeFeynman(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) } return rollupFee, nil @@ -166,7 +166,7 @@ func readGPOStorageSlots(addr common.Address, state StateDB) gpoState { gpoState.overhead = state.GetState(addr, rcfg.OverheadSlot).Big() gpoState.scalar = state.GetState(addr, rcfg.ScalarSlot).Big() gpoState.l1BlobBaseFee = state.GetState(addr, rcfg.L1BlobBaseFeeSlot).Big() - gpoState.execScalar = state.GetState(addr, rcfg.ExecScalarSlot).Big() + gpoState.commitScalar = state.GetState(addr, rcfg.CommitScalarSlot).Big() gpoState.blobScalar = state.GetState(addr, rcfg.BlobScalarSlot).Big() return gpoState } @@ -195,8 +195,8 @@ func calculateEncodedL1DataFeeCurie(data []byte, l1BaseFee *big.Int, l1BlobBaseF return l1DataFee } -// calculateEncodedRollupFeeFeeFeynman computes the L1 fee for an RLP-encoded tx, post Feynman -func calculateEncodedRollupFeeFeeFeynman( +// calculateEncodedL1DataFeeFeynman computes the L1 fee for an RLP-encoded tx, post Feynman +func calculateEncodedL1DataFeeFeynman( data []byte, l1BaseFee *big.Int, l1BlobBaseFee *big.Int, @@ -216,15 +216,15 @@ func calculateEncodedRollupFeeFeeFeynman( // fee per byte = execGas + blobGas feePerByte := new(big.Int).Add(execGas, blobGas) - // rollupFee = compression_ratio * tx_size * feePerByte - rollupFee := new(big.Int).Mul(compressionRatio, txSize) - rollupFee.Mul(rollupFee, feePerByte) + // l1DataFee = compression_ratio * tx_size * feePerByte + l1DataFee := new(big.Int).Mul(compressionRatio, txSize) + l1DataFee.Mul(l1DataFee, feePerByte) // Divide by rcfg.Precision (once for ratio, once for scalar) - rollupFee.Div(rollupFee, rcfg.Precision) - rollupFee.Div(rollupFee, rcfg.Precision) + l1DataFee.Div(l1DataFee, rcfg.Precision) + l1DataFee.Div(l1DataFee, rcfg.Precision) - return rollupFee + return l1DataFee } // calculateL1GasUsed computes the L1 gas used based on the calldata and @@ -272,23 +272,23 @@ func CalculateL1DataFee(tx *types.Transaction, state StateDB, config *params.Cha gpoState := readGPOStorageSlots(rcfg.L1GasPriceOracleAddress, state) - var rollupFee *big.Int + var l1DataFee *big.Int if !config.IsCurie(blockNumber) { - rollupFee = calculateEncodedL1DataFee(raw, gpoState.overhead, gpoState.l1BaseFee, gpoState.scalar) + l1DataFee = calculateEncodedL1DataFee(raw, gpoState.overhead, gpoState.l1BaseFee, gpoState.scalar) } else if !config.IsFeynman(blockNumber) { - rollupFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.execScalar, gpoState.blobScalar) + l1DataFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) } else { - rollupFee = calculateEncodedRollupFeeFeeFeynman(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.execScalar, gpoState.blobScalar) + l1DataFee = calculateEncodedL1DataFeeFeynman(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) } - // ensure rollupFee fits into uint64 for circuit compatibility + // ensure l1DataFee fits into uint64 for circuit compatibility // (note: in practice this value should never be this big) - if !rollupFee.IsUint64() { - rollupFee.SetUint64(math.MaxUint64) + if !l1DataFee.IsUint64() { + l1DataFee.SetUint64(math.MaxUint64) } - return rollupFee, nil + return l1DataFee, nil } func GetL1BaseFee(state StateDB) *big.Int { diff --git a/rollup/rcfg/config.go b/rollup/rcfg/config.go index bc692a88383a..3bac185c8302 100644 --- a/rollup/rcfg/config.go +++ b/rollup/rcfg/config.go @@ -32,7 +32,7 @@ var ( // New fields added in the Curie hard fork L1BlobBaseFeeSlot = common.BigToHash(big.NewInt(5)) - ExecScalarSlot = common.BigToHash(big.NewInt(6)) + CommitScalarSlot = common.BigToHash(big.NewInt(6)) BlobScalarSlot = common.BigToHash(big.NewInt(7)) IsCurieSlot = common.BigToHash(big.NewInt(8)) diff --git a/rollup/tracing/tracing.go b/rollup/tracing/tracing.go index 88d8b3110872..86fe1381c0e8 100644 --- a/rollup/tracing/tracing.go +++ b/rollup/tracing/tracing.go @@ -543,7 +543,7 @@ func (env *TraceEnv) fillBlockTrace(block *types.Block) (*types.BlockTrace, erro rcfg.OverheadSlot, rcfg.ScalarSlot, rcfg.L1BlobBaseFeeSlot, - rcfg.ExecScalarSlot, + rcfg.CommitScalarSlot, rcfg.BlobScalarSlot, rcfg.IsCurieSlot, }, From ce2498e47aa76d4d38b4c667f18cb23daf0cab71 Mon Sep 17 00:00:00 2001 From: Alejandro Ranchal-Pedrosa Date: Wed, 11 Jun 2025 17:36:49 +0200 Subject: [PATCH 06/23] Use blocktime not blocknumber --- accounts/abi/bind/backends/simulated.go | 2 +- cmd/evm/internal/t8ntool/execution.go | 2 +- core/state_prefetcher.go | 2 +- core/state_processor.go | 9 +++++---- core/tx_list.go | 4 ++-- core/tx_list_test.go | 4 ++-- core/tx_pool.go | 12 +++++++----- eth/state_accessor.go | 2 +- eth/tracers/api.go | 14 +++++++------- eth/tracers/api_test.go | 2 +- eth/tracers/internal/tracetest/calltrace_test.go | 6 +++--- eth/tracers/tracers_test.go | 2 +- internal/ethapi/api.go | 4 ++-- les/odr_test.go | 4 ++-- les/state_accessor.go | 2 +- light/odr_test.go | 2 +- light/txpool.go | 4 +++- rollup/fees/rollup_fee.go | 8 ++++---- rollup/tracing/tracing.go | 4 ++-- tests/state_test_util.go | 2 +- 20 files changed, 48 insertions(+), 43 deletions(-) diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 07216769915c..a4f51d425bd8 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -640,7 +640,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{NoBaseFee: true}) gasPool := new(core.GasPool).AddGas(math.MaxUint64) signer := types.MakeSigner(b.blockchain.Config(), head.Number, head.Time) - l1DataFee, err := fees.EstimateL1DataFeeForMessage(msg, head.BaseFee, b.blockchain.Config(), signer, stateDB, head.Number) + l1DataFee, err := fees.EstimateL1DataFeeForMessage(msg, head.BaseFee, b.blockchain.Config(), signer, stateDB, head.Number, head.Time) if err != nil { return nil, err } diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 922d10648e5e..fd71f24ac958 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -180,7 +180,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, snapshot := statedb.Snapshot() evm := vm.NewEVM(vmContext, txContext, statedb, chainConfig, vmConfig) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, chainConfig, new(big.Int).SetUint64(pre.Env.Number)) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) if err != nil { log.Info("rejected tx due to fees.CalculateL1DataFee", "index", i, "hash", tx.Hash(), "from", msg.From(), "error", err) rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()}) diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go index 7cdbf1dde696..5f31c0218516 100644 --- a/core/state_prefetcher.go +++ b/core/state_prefetcher.go @@ -71,7 +71,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c } statedb.SetTxContext(tx.Hash(), i) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, p.config, block.Number()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, p.config, block.Number(), block.Time()) if err != nil { return } diff --git a/core/state_processor.go b/core/state_processor.go index ddbc9d43bd43..dfd5018dfcb5 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -80,6 +80,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg header = block.Header() blockHash = block.Hash() blockNumber = block.Number() + blockTime = block.Time() allLogs []*types.Log gp = new(GasPool).AddGas(block.GasLimit()) ) @@ -105,7 +106,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } statedb.SetTxContext(tx.Hash(), i) - receipt, err := applyTransaction(msg, p.config, p.bc, nil, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv) + receipt, err := applyTransaction(msg, p.config, p.bc, nil, gp, statedb, blockNumber, blockTime, blockHash, tx, usedGas, vmenv) if err != nil { return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } @@ -120,7 +121,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg return receipts, allLogs, *usedGas, nil } -func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) { +func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockTime uint64, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) { defer func(t0 time.Time) { applyTransactionTimer.Update(time.Since(t0)) }(time.Now()) @@ -129,7 +130,7 @@ func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainCon txContext := NewEVMTxContext(msg) evm.Reset(txContext, statedb) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, config, blockNumber) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, config, blockNumber, blockTime) if err != nil { return nil, err } @@ -201,7 +202,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo // Create a new context to be used in the EVM environment blockContext := NewEVMBlockContext(header, bc, config, author) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg) - return applyTransaction(msg, config, bc, author, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv) + return applyTransaction(msg, config, bc, author, gp, statedb, header.Number, header.Time, header.Hash(), tx, usedGas, vmenv) } // ProcessParentBlockHash stores the parent block hash in the history storage contract diff --git a/core/tx_list.go b/core/tx_list.go index 73d646a87095..fba3b57f0bed 100644 --- a/core/tx_list.go +++ b/core/tx_list.go @@ -282,7 +282,7 @@ func (l *txList) Overlaps(tx *types.Transaction) bool { // // If the new transaction is accepted into the list, the lists' cost and gas // thresholds are also potentially updated. -func (l *txList) Add(tx *types.Transaction, state *state.StateDB, priceBump uint64, chainconfig *params.ChainConfig, blockNumber *big.Int) (bool, *types.Transaction) { +func (l *txList) Add(tx *types.Transaction, state *state.StateDB, priceBump uint64, chainconfig *params.ChainConfig, blockNumber *big.Int, blockTime uint64) (bool, *types.Transaction) { // If there's an older better transaction, abort old := l.txs.Get(tx.Nonce()) if old != nil { @@ -310,7 +310,7 @@ func (l *txList) Add(tx *types.Transaction, state *state.StateDB, priceBump uint l1DataFee := big.NewInt(0) if state != nil && chainconfig != nil { var err error - l1DataFee, err = fees.CalculateL1DataFee(tx, state, chainconfig, blockNumber) + l1DataFee, err = fees.CalculateL1DataFee(tx, state, chainconfig, blockNumber, blockTime) if err != nil { log.Error("Failed to calculate L1 data fee", "err", err, "tx", tx) return false, nil diff --git a/core/tx_list_test.go b/core/tx_list_test.go index 9b1cab4c406b..f0f0d9dcc0ad 100644 --- a/core/tx_list_test.go +++ b/core/tx_list_test.go @@ -38,7 +38,7 @@ func TestStrictTxListAdd(t *testing.T) { // Insert the transactions in a random order list := newTxList(true) for _, v := range rand.Perm(len(txs)) { - list.Add(txs[v], nil, DefaultTxPoolConfig.PriceBump, nil, nil) + list.Add(txs[v], nil, DefaultTxPoolConfig.PriceBump, nil, nil, 0) } // Verify internal state if len(list.txs.items) != len(txs) { @@ -65,7 +65,7 @@ func BenchmarkTxListAdd(b *testing.B) { for i := 0; i < b.N; i++ { list := newTxList(true) for _, v := range rand.Perm(len(txs)) { - list.Add(txs[v], nil, DefaultTxPoolConfig.PriceBump, nil, nil) + list.Add(txs[v], nil, DefaultTxPoolConfig.PriceBump, nil, nil, 0) list.Filter(priceLimit, DefaultTxPoolConfig.PriceBump) } } diff --git a/core/tx_pool.go b/core/tx_pool.go index 3d49800e0144..52f4b040d42c 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -301,6 +301,7 @@ type TxPool struct { currentState *state.StateDB // Current state in the blockchain head currentHead *big.Int // Current blockchain head + currentTime uint64 // Current blockchain head time pendingNonces *txNoncer // Pending state tracking virtual nonces currentMaxGas uint64 // Current gas limit for transaction caps @@ -838,7 +839,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { // 2. If FeeVault is enabled, perform an additional check for L1 data fees. if pool.chainconfig.Scroll.FeeVaultEnabled() { // Get L1 data fee in current state - l1DataFee, err := fees.CalculateL1DataFee(tx, pool.currentState, pool.chainconfig, pool.currentHead) + l1DataFee, err := fees.CalculateL1DataFee(tx, pool.currentState, pool.chainconfig, pool.currentHead, pool.currentTime) if err != nil { return fmt.Errorf("failed to calculate L1 data fee, err: %w", err) } @@ -947,7 +948,7 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err e from, _ := types.Sender(pool.signer, tx) // already validated if list := pool.pending[from]; list != nil && list.Overlaps(tx) { // Nonce already pending, check if required price bump is met - inserted, old := list.Add(tx, pool.currentState, pool.config.PriceBump, pool.chainconfig, pool.currentHead) + inserted, old := list.Add(tx, pool.currentState, pool.config.PriceBump, pool.chainconfig, pool.currentHead, pool.currentTime) if !inserted { log.Debug("Discarding underpriced pending transaction", "hash", hash.Hex(), "gasTipCap", tx.GasTipCap(), "gasFeeCap", tx.GasFeeCap()) pendingDiscardMeter.Mark(1) @@ -1001,7 +1002,7 @@ func (pool *TxPool) enqueueTx(hash common.Hash, tx *types.Transaction, local boo pool.queue[from] = newTxList(false) } - inserted, old := pool.queue[from].Add(tx, pool.currentState, pool.config.PriceBump, pool.chainconfig, pool.currentHead) + inserted, old := pool.queue[from].Add(tx, pool.currentState, pool.config.PriceBump, pool.chainconfig, pool.currentHead, pool.currentTime) if !inserted { // An older transaction was better, discard this log.Debug("Discarding underpriced queued transaction", "hash", hash.Hex(), "gasTipCap", tx.GasTipCap(), "gasFeeCap", tx.GasFeeCap()) @@ -1068,7 +1069,7 @@ func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.T return false } - inserted, old := list.Add(tx, pool.currentState, pool.config.PriceBump, pool.chainconfig, pool.currentHead) + inserted, old := list.Add(tx, pool.currentState, pool.config.PriceBump, pool.chainconfig, pool.currentHead, pool.currentTime) if !inserted { // An older transaction was better, discard this log.Debug("Discarding underpriced pending transaction", "hash", hash.Hex(), "gasTipCap", tx.GasTipCap(), "gasFeeCap", tx.GasFeeCap()) @@ -1603,6 +1604,7 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) { // Update current head pool.currentHead = next + pool.currentTime = newHead.Time } // promoteExecutables moves transactions that have become processable from the @@ -1690,7 +1692,7 @@ func (pool *TxPool) executableTxFilter(costLimit *big.Int) func(tx *types.Transa if pool.chainconfig.Scroll.FeeVaultEnabled() { // recheck L1 data fee, as the oracle price may have changed - l1DataFee, err := fees.CalculateL1DataFee(tx, pool.currentState, pool.chainconfig, pool.currentHead) + l1DataFee, err := fees.CalculateL1DataFee(tx, pool.currentState, pool.chainconfig, pool.currentHead, pool.currentTime) if err != nil { log.Error("Failed to calculate L1 data fee", "err", err, "tx", tx) return false diff --git a/eth/state_accessor.go b/eth/state_accessor.go index 13b80ded0375..f4a75fc59485 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -198,7 +198,7 @@ func (eth *Ethereum) stateAtTransaction(block *types.Block, txIndex int, reexec // Not yet the searched for transaction, execute on top of the current state vmenv := vm.NewEVM(context, txContext, statedb, eth.blockchain.Config(), vm.Config{}) statedb.SetTxContext(tx.Hash(), idx) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, eth.blockchain.Config(), block.Number()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, eth.blockchain.Config(), block.Number(), block.Time()) if err != nil { return nil, vm.BlockContext{}, nil, err } diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 7b66326c0970..cdfa276cba25 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -292,7 +292,7 @@ func (api *API) traceChain(ctx context.Context, start, end *types.Block, config TxHash: tx.Hash(), } - l1DataFee, err := fees.CalculateL1DataFee(tx, task.statedb, api.backend.ChainConfig(), task.block.Number()) + l1DataFee, err := fees.CalculateL1DataFee(tx, task.statedb, api.backend.ChainConfig(), task.block.Number(), task.block.Time()) if err != nil { // though it's not a "tracing error", we still need to put it here task.results[i] = &txTraceResult{Error: err.Error()} @@ -557,7 +557,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config ) statedb.SetTxContext(tx.Hash(), i) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) if err != nil { log.Warn("Tracing intermediate roots did not complete due to fees.CalculateL1DataFee", "txindex", i, "txhash", tx.Hash(), "err", err) return nil, err @@ -645,7 +645,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac TxHash: txs[task.index].Hash(), } - l1DataFee, err := fees.CalculateL1DataFee(txs[task.index], task.statedb, api.backend.ChainConfig(), block.Number()) + l1DataFee, err := fees.CalculateL1DataFee(txs[task.index], task.statedb, api.backend.ChainConfig(), block.Number(), block.Time()) if err != nil { // though it's not a "tracing error", we still need to put it here results[task.index] = &txTraceResult{ @@ -679,7 +679,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac msg, _ := tx.AsMessage(signer, block.BaseFee()) statedb.SetTxContext(tx.Hash(), i) vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, api.backend.ChainConfig(), vm.Config{}) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) if err != nil { failed = err break @@ -804,7 +804,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block // Execute the transaction and flush any traces to disk vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf) statedb.SetTxContext(tx.Hash(), i) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) if err == nil { _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()), l1DataFee) } @@ -869,7 +869,7 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config * TxIndex: int(index), TxHash: hash, } - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) if err != nil { return nil, err } @@ -929,7 +929,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc } signer := types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) - l1DataFee, err := fees.EstimateL1DataFeeForMessage(msg, block.BaseFee(), api.backend.ChainConfig(), signer, statedb, block.Number()) + l1DataFee, err := fees.EstimateL1DataFeeForMessage(msg, block.BaseFee(), api.backend.ChainConfig(), signer, statedb, block.Number(), block.Time()) if err != nil { return nil, err } diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index d49e7df80a4c..47b8b4c6ac9a 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -173,7 +173,7 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block return msg, context, statedb, nil } vmenv := vm.NewEVM(context, txContext, statedb, b.chainConfig, vm.Config{}) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, b.chainConfig, block.Number()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, b.chainConfig, block.Number(), block.Time()) if err != nil { return nil, vm.BlockContext{}, nil, err } diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go index c3d8bfff39ea..5ee8905fa46c 100644 --- a/eth/tracers/internal/tracetest/calltrace_test.go +++ b/eth/tracers/internal/tracetest/calltrace_test.go @@ -193,7 +193,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) { if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, test.Genesis.Config, context.BlockNumber) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, test.Genesis.Config, context.BlockNumber, context.Time.Uint64()) if err != nil { t.Fatalf("failed to calculate l1DataFee: %v", err) } @@ -308,7 +308,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) { } evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer}) snap := statedb.Snapshot() - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, test.Genesis.Config, context.BlockNumber) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, test.Genesis.Config, context.BlockNumber, context.Time.Uint64()) if err != nil { b.Fatalf("failed to calculate l1DataFee: %v", err) } @@ -381,7 +381,7 @@ func TestZeroValueToNotExitCall(t *testing.T) { if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, params.MainnetChainConfig, context.BlockNumber) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, params.MainnetChainConfig, context.BlockNumber, context.Time.Uint64()) if err != nil { t.Fatalf("failed to calculate l1DataFee: %v", err) } diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go index 4a18a9245c73..addd2b8cdb2a 100644 --- a/eth/tracers/tracers_test.go +++ b/eth/tracers/tracers_test.go @@ -112,7 +112,7 @@ func BenchmarkTransactionTrace(b *testing.B) { for i := 0; i < b.N; i++ { snap := statedb.Snapshot() - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, params.AllEthashProtocolChanges, context.BlockNumber) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, params.AllEthashProtocolChanges, context.BlockNumber, context.Time.Uint64()) if err != nil { b.Fatal(err) } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index d9978b7ac592..f41090a8c42d 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -999,7 +999,7 @@ func EstimateL1MsgFee(ctx context.Context, b Backend, args TransactionArgs, bloc }() signer := types.MakeSigner(config, header.Number, header.Time) - return fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, config, signer, evm.StateDB, header.Number) + return fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, config, signer, evm.StateDB, header.Number, header.Time) } func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) { @@ -1595,7 +1595,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH return nil, 0, nil, err } signer := types.MakeSigner(b.ChainConfig(), header.Number, header.Time) - l1DataFee, err := fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, b.ChainConfig(), signer, statedb, header.Number) + l1DataFee, err := fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, b.ChainConfig(), signer, statedb, header.Number, header.Time) if err != nil { return nil, 0, nil, fmt.Errorf("failed to apply transaction: %v err: %v", args.toTransaction().Hash(), err) } diff --git a/les/odr_test.go b/les/odr_test.go index e5ab5410f305..a8cee131b708 100644 --- a/les/odr_test.go +++ b/les/odr_test.go @@ -145,7 +145,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai //vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{}) gp := new(core.GasPool).AddGas(math.MaxUint64) signer := types.MakeSigner(config, header.Number, header.Time) - l1DataFee, _ := fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, config, signer, statedb, header.Number) + l1DataFee, _ := fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, config, signer, statedb, header.Number, header.Time) result, _ := core.ApplyMessage(vmenv, msg, gp, l1DataFee) res = append(res, result.Return()...) } @@ -159,7 +159,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai vmenv := vm.NewEVM(context, txContext, state, config, vm.Config{NoBaseFee: true}) gp := new(core.GasPool).AddGas(math.MaxUint64) signer := types.MakeSigner(config, header.Number, header.Time) - l1DataFee, _ := fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, config, signer, state, header.Number) + l1DataFee, _ := fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, config, signer, state, header.Number, header.Time) result, _ := core.ApplyMessage(vmenv, msg, gp, l1DataFee) if state.Error() == nil { res = append(res, result.Return()...) diff --git a/les/state_accessor.go b/les/state_accessor.go index c0db2715f439..b2afa28938cf 100644 --- a/les/state_accessor.go +++ b/les/state_accessor.go @@ -65,7 +65,7 @@ func (leth *LightEthereum) stateAtTransaction(ctx context.Context, block *types. } // Not yet the searched for transaction, execute on top of the current state vmenv := vm.NewEVM(context, txContext, statedb, leth.blockchain.Config(), vm.Config{}) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, leth.blockchain.Config(), block.Number()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, leth.blockchain.Config(), block.Number(), block.Time()) if err != nil { return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) } diff --git a/light/odr_test.go b/light/odr_test.go index a122207d22bc..ce5fae9146da 100644 --- a/light/odr_test.go +++ b/light/odr_test.go @@ -201,7 +201,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain vmenv := vm.NewEVM(context, txContext, st, config, vm.Config{NoBaseFee: true}) gp := new(core.GasPool).AddGas(math.MaxUint64) signer := types.MakeSigner(config, header.Number, header.Time) - l1DataFee, _ := fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, config, signer, st, header.Number) + l1DataFee, _ := fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, config, signer, st, header.Number, header.Time) result, _ := core.ApplyMessage(vmenv, msg, gp, l1DataFee) res = append(res, result.Return()...) if st.Error() != nil { diff --git a/light/txpool.go b/light/txpool.go index ec311d927e2c..e366fdc9639b 100644 --- a/light/txpool.go +++ b/light/txpool.go @@ -74,6 +74,7 @@ type TxPool struct { shanghai bool // Fork indicator whether we are in the shanghai stage. currentHead *big.Int // Current blockchain head + currentTime uint64 // Current blockchain head time } // TxRelayBackend provides an interface to the mechanism that forwards transacions @@ -326,6 +327,7 @@ func (pool *TxPool) setNewHead(head *types.Header) { pool.shanghai = pool.config.IsShanghai(next) pool.currentHead = next + pool.currentTime = head.Time } // Stop stops the light transaction pool @@ -408,7 +410,7 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error // 2. If FeeVault is enabled, perform an additional check for L1 data fees. if pool.config.Scroll.FeeVaultEnabled() { // Get L1 data fee in current state - l1DataFee, err := fees.CalculateL1DataFee(tx, currentState, pool.config, pool.currentHead) + l1DataFee, err := fees.CalculateL1DataFee(tx, currentState, pool.config, pool.currentHead, pool.currentTime) if err != nil { return fmt.Errorf("failed to calculate L1 data fee, err: %w", err) } diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index 55d88359c8e9..c7fa36ad6510 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -62,7 +62,7 @@ type gpoState struct { blobScalar *big.Int } -func EstimateL1DataFeeForMessage(msg Message, baseFee *big.Int, config *params.ChainConfig, signer types.Signer, state StateDB, blockNumber *big.Int) (*big.Int, error) { +func EstimateL1DataFeeForMessage(msg Message, baseFee *big.Int, config *params.ChainConfig, signer types.Signer, state StateDB, blockNumber *big.Int, blockTime uint64) (*big.Int, error) { if msg.IsL1MessageTx() { return big.NewInt(0), nil } @@ -85,7 +85,7 @@ func EstimateL1DataFeeForMessage(msg Message, baseFee *big.Int, config *params.C if !config.IsCurie(blockNumber) { rollupFee = calculateEncodedL1DataFee(raw, gpoState.overhead, gpoState.l1BaseFee, gpoState.scalar) - } else if !config.IsFeynman(blockNumber) { + } else if !config.IsFeynman(blockTime) { rollupFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) } else { rollupFee = calculateEncodedL1DataFeeFeynman(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) @@ -267,7 +267,7 @@ func mulAndScale(x *big.Int, y *big.Int, precision *big.Int) *big.Int { return new(big.Int).Quo(z, precision) } -func CalculateL1DataFee(tx *types.Transaction, state StateDB, config *params.ChainConfig, blockNumber *big.Int) (*big.Int, error) { +func CalculateL1DataFee(tx *types.Transaction, state StateDB, config *params.ChainConfig, blockNumber *big.Int, blockTime uint64) (*big.Int, error) { if tx.IsL1MessageTx() { return big.NewInt(0), nil } @@ -283,7 +283,7 @@ func CalculateL1DataFee(tx *types.Transaction, state StateDB, config *params.Cha if !config.IsCurie(blockNumber) { l1DataFee = calculateEncodedL1DataFee(raw, gpoState.overhead, gpoState.l1BaseFee, gpoState.scalar) - } else if !config.IsFeynman(blockNumber) { + } else if !config.IsFeynman(blockTime) { l1DataFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) } else { l1DataFee = calculateEncodedL1DataFeeFeynman(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) diff --git a/rollup/tracing/tracing.go b/rollup/tracing/tracing.go index 86fe1381c0e8..0569a99bc475 100644 --- a/rollup/tracing/tracing.go +++ b/rollup/tracing/tracing.go @@ -239,7 +239,7 @@ func (env *TraceEnv) GetBlockTrace(block *types.Block) (*types.BlockTrace, error msg, _ := tx.AsMessage(env.signer, block.BaseFee()) env.state.SetTxContext(tx.Hash(), i) vmenv := vm.NewEVM(env.blockCtx, core.NewEVMTxContext(msg), env.state, env.chainConfig, vm.Config{}) - l1DataFee, err := fees.CalculateL1DataFee(tx, env.state, env.chainConfig, block.Number()) + l1DataFee, err := fees.CalculateL1DataFee(tx, env.state, env.chainConfig, block.Number(), block.Time()) if err != nil { failed = err break @@ -342,7 +342,7 @@ func (env *TraceEnv) getTxResult(state *state.StateDB, index int, block *types.B state.SetTxContext(txctx.TxHash, txctx.TxIndex) // Computes the new state by applying the given message. - l1DataFee, err := fees.CalculateL1DataFee(tx, state, env.chainConfig, block.Number()) + l1DataFee, err := fees.CalculateL1DataFee(tx, state, env.chainConfig, block.Number(), block.Time()) if err != nil { return err } diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 6cb06777e546..9f3a5da75a98 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -251,7 +251,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh gaspool := new(core.GasPool) gaspool.AddGas(block.GasLimit()) - l1DataFee, err := fees.CalculateL1DataFee(&ttx, statedb, config, block.Number()) + l1DataFee, err := fees.CalculateL1DataFee(&ttx, statedb, config, block.Number(), block.Time()) if err != nil { return nil, nil, common.Hash{}, err } From 2b061e4a4a0a5e5fb23b1232ae3c3840392c7c2c Mon Sep 17 00:00:00 2001 From: Alejandro Ranchal-Pedrosa Date: Wed, 11 Jun 2025 18:11:28 +0200 Subject: [PATCH 07/23] Add unit test --- rollup/fees/rollup_fee_test.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/rollup/fees/rollup_fee_test.go b/rollup/fees/rollup_fee_test.go index b35d8cd9bf55..9de3fa015d18 100644 --- a/rollup/fees/rollup_fee_test.go +++ b/rollup/fees/rollup_fee_test.go @@ -31,3 +31,28 @@ func TestL1DataFeeAfterCurie(t *testing.T) { actual := calculateEncodedL1DataFeeCurie(data, l1BaseFee, l1BlobBaseFee, commitScalar, blobScalar) assert.Equal(t, expected, actual) } +func TestL1DataFeeFeynman(t *testing.T) { + // You may want to import rcfg in your test file + + l1BaseFee := new(big.Int).SetInt64(1_000_000_000) + l1BlobBaseFee := new(big.Int).SetInt64(1_000_000_000) + execScalar := new(big.Int).SetInt64(10) + blobScalar := new(big.Int).SetInt64(20) + data := make([]byte, 10) // txSize = 10 + + // feePerByte = execScalar * l1BaseFee + blobScalar * l1BlobBaseFee = 10_000_000_000 + 20_000_000_000 = 30_000_000_000 + // l1DataFee = precision * txSize * feePerByte / precision / precision + // = 1_000_000 * 10 * 30_000_000_000 / 1_000_000 / 1_000_000 = 300_000_000_000_000_000 / 1_000_000 / 1_000_000_000 = 300 + + expected := new(big.Int).SetInt64(300) + + actual := calculateEncodedL1DataFeeFeynman( + data, + l1BaseFee, + l1BlobBaseFee, + execScalar, + blobScalar, + ) + + assert.Equal(t, expected, actual) +} From c3c559530ecdcaccb72c613b2946edd3d44669dd Mon Sep 17 00:00:00 2001 From: Alejandro Ranchal-Pedrosa Date: Wed, 11 Jun 2025 18:14:13 +0200 Subject: [PATCH 08/23] Clarify test comment --- rollup/fees/rollup_fee_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rollup/fees/rollup_fee_test.go b/rollup/fees/rollup_fee_test.go index 9de3fa015d18..2fc3494067d6 100644 --- a/rollup/fees/rollup_fee_test.go +++ b/rollup/fees/rollup_fee_test.go @@ -42,7 +42,8 @@ func TestL1DataFeeFeynman(t *testing.T) { // feePerByte = execScalar * l1BaseFee + blobScalar * l1BlobBaseFee = 10_000_000_000 + 20_000_000_000 = 30_000_000_000 // l1DataFee = precision * txSize * feePerByte / precision / precision - // = 1_000_000 * 10 * 30_000_000_000 / 1_000_000 / 1_000_000 = 300_000_000_000_000_000 / 1_000_000 / 1_000_000_000 = 300 + // = 1_000_000_000 * 10 * 30_000_000_000 / 1_000_000_000 / 1_000_000 = 300_000_000_000_000_000 / 1_000_000_000 / 1_000_000_000 = 300 + //TODO for now compression_ratio = precision, placeholder expected := new(big.Int).SetInt64(300) From 61af0234fee53f89f8ef2b52cd953ff2758f9d22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Tue, 24 Jun 2025 19:49:28 +0200 Subject: [PATCH 09/23] feat(feynman): upgrade gas oracle predeploy --- cmd/evm/internal/t8ntool/execution.go | 4 ++++ consensus/misc/feynman.go | 22 ++++++++++++++++++++++ core/chain_makers.go | 3 +++ core/state_processor.go | 5 +++++ miner/scroll_worker.go | 15 ++++++++++----- params/config.go | 5 +++++ params/version.go | 2 +- rollup/rcfg/config.go | 18 ++++++++++++++++++ 8 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 consensus/misc/feynman.go diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 922d10648e5e..2f237110ddbb 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -152,6 +152,10 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, if chainConfig.CurieBlock != nil && chainConfig.CurieBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 { misc.ApplyCurieHardFork(statedb) } + // Apply Feynman hard fork + if chainConfig.IsFeynmanTransitionBlock(pre.Env.Timestamp, pre.Env.ParentTimestamp) { + misc.ApplyFeynmanHardFork(statedb) + } // Apply EIP-2935 if pre.Env.BlockHashes != nil && chainConfig.IsFeynman(pre.Env.Timestamp) { var ( diff --git a/consensus/misc/feynman.go b/consensus/misc/feynman.go new file mode 100644 index 000000000000..b933187cf9ee --- /dev/null +++ b/consensus/misc/feynman.go @@ -0,0 +1,22 @@ +package misc + +import ( + "github.com/scroll-tech/go-ethereum/common" + "github.com/scroll-tech/go-ethereum/core/state" + "github.com/scroll-tech/go-ethereum/log" + "github.com/scroll-tech/go-ethereum/rollup/rcfg" +) + +// ApplyFeynmanHardFork modifies the state database according to the Feynman hard-fork rules, +// updating the bytecode and storage of the L1GasPriceOracle contract. +func ApplyFeynmanHardFork(statedb *state.StateDB) { + log.Info("Applying Feynman hard fork") + + // update contract byte code + statedb.SetCode(rcfg.L1GasPriceOracleAddress, rcfg.FeynmanL1GasPriceOracleBytecode) + + // initialize new storage slots + statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.IsFeynmanSlot, common.BytesToHash([]byte{1})) + statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.PenaltyThresholdSlot, common.BigToHash(rcfg.InitialPenaltyThreshold)) + statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.PenaltyFactorSlot, common.BigToHash(rcfg.InitialPenaltyFactor)) +} diff --git a/core/chain_makers.go b/core/chain_makers.go index 47a7d9fab847..b37ed9c3eeec 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -249,6 +249,9 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse if config.CurieBlock != nil && config.CurieBlock.Cmp(b.header.Number) == 0 { misc.ApplyCurieHardFork(statedb) } + if config.IsFeynmanTransitionBlock(b.Time(), parent.Time()) { + misc.ApplyFeynmanHardFork(statedb) + } // Execute any user modifications to the block if gen != nil { gen(i, b) diff --git a/core/state_processor.go b/core/state_processor.go index ddbc9d43bd43..d031bc848adf 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -91,6 +91,11 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg if p.config.CurieBlock != nil && p.config.CurieBlock.Cmp(block.Number()) == 0 { misc.ApplyCurieHardFork(statedb) } + // Apply Feynman hard fork + parent := p.bc.GetHeaderByHash(block.ParentHash()) + if p.config.IsFeynmanTransitionBlock(block.Time(), parent.Time) { + misc.ApplyFeynmanHardFork(statedb) + } blockContext := NewEVMBlockContext(header, p.bc, p.config, nil) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg) processorBlockTransactionGauge.Update(int64(block.Transactions().Len())) diff --git a/miner/scroll_worker.go b/miner/scroll_worker.go index 8af97f1cd7a9..52f0a3057a1e 100644 --- a/miner/scroll_worker.go +++ b/miner/scroll_worker.go @@ -464,8 +464,7 @@ func (w *worker) collectPendingL1Messages(startIndex uint64) []types.L1MessageTx } // newWork -func (w *worker) newWork(now time.Time, parentHash common.Hash, reorging bool, reorgReason error) error { - parent := w.chain.GetBlockByHash(parentHash) +func (w *worker) newWork(now time.Time, parent *types.Block, reorging bool, reorgReason error) error { header := &types.Header{ ParentHash: parent.Hash(), Number: new(big.Int).Add(parent.Number(), common.Big1), @@ -586,13 +585,14 @@ func (w *worker) newWork(now time.Time, parentHash common.Hash, reorging bool, r } // tryCommitNewWork -func (w *worker) tryCommitNewWork(now time.Time, parent common.Hash, reorging bool, reorgReason error) (common.Hash, error) { +func (w *worker) tryCommitNewWork(now time.Time, parentHash common.Hash, reorging bool, reorgReason error) (common.Hash, error) { + parent := w.chain.GetBlockByHash(parentHash) err := w.newWork(now, parent, reorging, reorgReason) if err != nil { return common.Hash{}, fmt.Errorf("failed creating new work: %w", err) } - shouldCommit, err := w.handleForks() + shouldCommit, err := w.handleForks(parent) if err != nil { return common.Hash{}, fmt.Errorf("failed handling forks: %w", err) } @@ -626,7 +626,7 @@ func (w *worker) tryCommitNewWork(now time.Time, parent common.Hash, reorging bo } // handleForks -func (w *worker) handleForks() (bool, error) { +func (w *worker) handleForks(parent *types.Block) (bool, error) { // Apply Curie predeployed contract update if w.chainConfig.CurieBlock != nil && w.chainConfig.CurieBlock.Cmp(w.current.header.Number) == 0 { misc.ApplyCurieHardFork(w.current.state) @@ -639,6 +639,11 @@ func (w *worker) handleForks() (bool, error) { return parent != nil && !w.chainConfig.IsEuclid(parent.Time()), nil } + // Apply Feynman hard fork + if w.chainConfig.IsFeynmanTransitionBlock(w.current.header.Time, parent.Time()) { + misc.ApplyFeynmanHardFork(w.current.state) + } + // Apply EIP-2935 if w.chainConfig.IsFeynman(w.current.header.Time) { context := core.NewEVMBlockContext(w.current.header, w.chain, w.chainConfig, nil) diff --git a/params/config.go b/params/config.go index eda4340e80c4..d859f6384dea 100644 --- a/params/config.go +++ b/params/config.go @@ -1002,6 +1002,11 @@ func (c *ChainConfig) IsFeynman(now uint64) bool { return isForkedTime(now, c.FeynmanTime) } +// IsFeynmanTransitionBlock returns whether the given block timestamp corresponds to the first Feynman block. +func (c *ChainConfig) IsFeynmanTransitionBlock(blockTimestamp uint64, parentTimestamp uint64) bool { + return isForkedTime(blockTimestamp, c.FeynmanTime) && !isForkedTime(parentTimestamp, c.FeynmanTime) +} + // IsTerminalPoWBlock returns whether the given block is the last block of PoW stage. func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *big.Int) bool { if c.TerminalTotalDifficulty == nil { diff --git a/params/version.go b/params/version.go index f8f2cbeb11ba..13fa655ad50b 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 = 8 // Minor version component of the current release - VersionPatch = 57 // Patch version component of the current release + VersionPatch = 58 // Patch version component of the current release VersionMeta = "mainnet" // Version metadata to append to the version string ) diff --git a/rollup/rcfg/config.go b/rollup/rcfg/config.go index 3bac185c8302..9ba9f7cf97b3 100644 --- a/rollup/rcfg/config.go +++ b/rollup/rcfg/config.go @@ -48,6 +48,24 @@ var ( // FOUNDRY_EVM_VERSION="cancun" forge build // cat artifacts/src/L1GasPriceOracle.sol/L1GasPriceOracle.json | jq -r .deployedBytecode.object CurieL1GasPriceOracleBytecode = common.Hex2Bytes("608060405234801561000f575f80fd5b5060043610610132575f3560e01c8063715018a6116100b4578063a911d77f11610079578063a911d77f1461024c578063bede39b514610254578063de26c4a114610267578063e88a60ad1461027a578063f2fde38b1461028d578063f45e65d8146102a0575f80fd5b8063715018a6146101eb57806384189161146101f35780638da5cb5b146101fc57806393e59dc114610226578063944b247f14610239575f80fd5b80633d0f963e116100fa5780633d0f963e146101a057806349948e0e146101b3578063519b4bd3146101c65780636a5e67e5146101cf57806370465597146101d8575f80fd5b80630c18c1621461013657806313dad5be1461015257806323e524ac1461016f5780633577afc51461017857806339455d3a1461018d575b5f80fd5b61013f60025481565b6040519081526020015b60405180910390f35b60085461015f9060ff1681565b6040519015158152602001610149565b61013f60065481565b61018b6101863660046109b3565b6102a9565b005b61018b61019b3660046109ca565b61033b565b61018b6101ae3660046109ea565b610438565b61013f6101c1366004610a2b565b6104bb565b61013f60015481565b61013f60075481565b61018b6101e63660046109b3565b6104e0565b61018b61056e565b61013f60055481565b5f5461020e906001600160a01b031681565b6040516001600160a01b039091168152602001610149565b60045461020e906001600160a01b031681565b61018b6102473660046109b3565b6105a2565b61018b61062e565b61018b6102623660046109b3565b61068a565b61013f610275366004610a2b565b610747565b61018b6102883660046109b3565b610764565b61018b61029b3660046109ea565b6107f0565b61013f60035481565b5f546001600160a01b031633146102db5760405162461bcd60e51b81526004016102d290610ad6565b60405180910390fd5b621c9c388111156102ff57604051635742c80560e11b815260040160405180910390fd5b60028190556040518181527f32740b35c0ea213650f60d44366b4fb211c9033b50714e4a1d34e65d5beb9bb4906020015b60405180910390a150565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa158015610382573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103a69190610b0d565b6103c3576040516326b3506d60e11b815260040160405180910390fd5b600182905560058190556040518281527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c449060200160405180910390a16040518181527f9a14bfb5d18c4c3cf14cae19c23d7cf1bcede357ea40ca1f75cd49542c71c214906020015b60405180910390a15050565b5f546001600160a01b031633146104615760405162461bcd60e51b81526004016102d290610ad6565b600480546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f22d1c35fe072d2e42c3c8f9bd4a0d34aa84a0101d020a62517b33fdb3174e5f7910161042c565b6008545f9060ff16156104d7576104d18261087b565b92915050565b6104d1826108c1565b5f546001600160a01b031633146105095760405162461bcd60e51b81526004016102d290610ad6565b610519633b9aca006103e8610b40565b81111561053957604051631e44fdeb60e11b815260040160405180910390fd5b60038190556040518181527f3336cd9708eaf2769a0f0dc0679f30e80f15dcd88d1921b5a16858e8b85c591a90602001610330565b5f546001600160a01b031633146105975760405162461bcd60e51b81526004016102d290610ad6565b6105a05f610904565b565b5f546001600160a01b031633146105cb5760405162461bcd60e51b81526004016102d290610ad6565b6105d9633b9aca0080610b40565b8111156105f95760405163874f603160e01b815260040160405180910390fd5b60068190556040518181527f2ab3f5a4ebbcbf3c24f62f5454f52f10e1a8c9dcc5acac8f19199ce881a6a10890602001610330565b5f546001600160a01b031633146106575760405162461bcd60e51b81526004016102d290610ad6565b60085460ff161561067b576040516379f9c57560e01b815260040160405180910390fd5b6008805460ff19166001179055565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa1580156106d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f59190610b0d565b610712576040516326b3506d60e11b815260040160405180910390fd5b60018190556040518181527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c4490602001610330565b6008545f9060ff161561075b57505f919050565b6104d182610953565b5f546001600160a01b0316331461078d5760405162461bcd60e51b81526004016102d290610ad6565b61079b633b9aca0080610b40565b8111156107bb5760405163f37ec21560e01b815260040160405180910390fd5b60078190556040518181527f6b332a036d8c3ead57dcb06c87243bd7a2aed015ddf2d0528c2501dae56331aa90602001610330565b5f546001600160a01b031633146108195760405162461bcd60e51b81526004016102d290610ad6565b6001600160a01b03811661086f5760405162461bcd60e51b815260206004820152601d60248201527f6e6577206f776e657220697320746865207a65726f206164647265737300000060448201526064016102d2565b61087881610904565b50565b5f633b9aca0060055483516007546108939190610b40565b61089d9190610b40565b6001546006546108ad9190610b40565b6108b79190610b57565b6104d19190610b6a565b5f806108cc83610953565b90505f600154826108dd9190610b40565b9050633b9aca00600354826108f29190610b40565b6108fc9190610b6a565b949350505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80515f908190815b818110156109a45784818151811061097557610975610b89565b01602001516001600160f81b0319165f036109955760048301925061099c565b6010830192505b60010161095b565b50506002540160400192915050565b5f602082840312156109c3575f80fd5b5035919050565b5f80604083850312156109db575f80fd5b50508035926020909101359150565b5f602082840312156109fa575f80fd5b81356001600160a01b0381168114610a10575f80fd5b9392505050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215610a3b575f80fd5b813567ffffffffffffffff80821115610a52575f80fd5b818401915084601f830112610a65575f80fd5b813581811115610a7757610a77610a17565b604051601f8201601f19908116603f01168101908382118183101715610a9f57610a9f610a17565b81604052828152876020848701011115610ab7575f80fd5b826020860160208301375f928101602001929092525095945050505050565b60208082526017908201527f63616c6c6572206973206e6f7420746865206f776e6572000000000000000000604082015260600190565b5f60208284031215610b1d575f80fd5b81518015158114610a10575f80fd5b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176104d1576104d1610b2c565b808201808211156104d1576104d1610b2c565b5f82610b8457634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffdfea26469706673582212200c2ac583f18be4f94ab169ae6f2ea3a708a7c0d4424746b120b177adb39e626064736f6c63430008180033") + + // New fields added in the Feynman hard fork + PenaltyThresholdSlot = common.BigToHash(big.NewInt(9)) + PenaltyFactorSlot = common.BigToHash(big.NewInt(10)) + IsFeynmanSlot = common.BigToHash(big.NewInt(11)) + + InitialPenaltyThreshold = big.NewInt(1_000_000_000) + InitialPenaltyFactor = big.NewInt(1_000_000_000) + + // FeynmanL1GasPriceOracleBytecode is the new (compression-penalty-enabled) gas price oracle after + // the Feynman hard fork. Run these commands in the monorepo to verify this bytecode: + // + // git checkout TBA + // cd contracts + // yarn + // FOUNDRY_EVM_VERSION="cancun" forge build + // cat artifacts/src/L1GasPriceOracle.sol/L1GasPriceOracle.json | jq -r .deployedBytecode.object + FeynmanL1GasPriceOracleBytecode = common.Hex2Bytes("608060405234801561000f575f80fd5b50600436106101a1575f3560e01c806384189161116100f3578063c63b9e2d11610093578063e88a60ad1161006e578063e88a60ad1461032e578063f2fde38b14610341578063f45e65d814610354578063fe5b04151461035d575f80fd5b8063c63b9e2d146102ff578063c91e514914610312578063de26c4a11461031b575f80fd5b8063944b247f116100ce578063944b247f146102be578063a911d77f146102d1578063aa5e9334146102d9578063bede39b5146102ec575f80fd5b806384189161146102785780638da5cb5b1461028157806393e59dc1146102ab575f80fd5b80633d0f963e1161015e5780636112d6db116101395780636112d6db1461024b5780636a5e67e514610254578063704655971461025d578063715018a614610270575f80fd5b80633d0f963e1461021c57806349948e0e1461022f578063519b4bd314610242575f80fd5b80630c18c162146101a557806313dad5be146101c157806323e524ac146101de5780633577afc5146101e757806339455d3a146101fc5780633b7656bb1461020f575b5f80fd5b6101ae60025481565b6040519081526020015b60405180910390f35b6008546101ce9060ff1681565b60405190151581526020016101b8565b6101ae60065481565b6101fa6101f5366004610c73565b610365565b005b6101fa61020a366004610c8a565b6103f7565b600b546101ce9060ff1681565b6101fa61022a366004610caa565b6104f4565b6101ae61023d366004610ceb565b610577565b6101ae60015481565b6101ae600a5481565b6101ae60075481565b6101fa61026b366004610c73565b6105b0565b6101fa61063e565b6101ae60055481565b5f54610293906001600160a01b031681565b6040516001600160a01b0390911681526020016101b8565b600454610293906001600160a01b031681565b6101fa6102cc366004610c73565b610672565b6101fa6106fe565b6101fa6102e7366004610c73565b61075a565b6101fa6102fa366004610c73565b6107f4565b6101fa61030d366004610c73565b6108b1565b6101ae60095481565b6101ae610329366004610ceb565b61094a565b6101fa61033c366004610c73565b610974565b6101fa61034f366004610caa565b610a00565b6101ae60035481565b6101fa610a8b565b5f546001600160a01b031633146103975760405162461bcd60e51b815260040161038e90610d96565b60405180910390fd5b621c9c388111156103bb57604051635742c80560e11b815260040160405180910390fd5b60028190556040518181527f32740b35c0ea213650f60d44366b4fb211c9033b50714e4a1d34e65d5beb9bb4906020015b60405180910390a150565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa15801561043e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104629190610dcd565b61047f576040516326b3506d60e11b815260040160405180910390fd5b600182905560058190556040518281527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c449060200160405180910390a16040518181527f9a14bfb5d18c4c3cf14cae19c23d7cf1bcede357ea40ca1f75cd49542c71c214906020015b60405180910390a15050565b5f546001600160a01b0316331461051d5760405162461bcd60e51b815260040161038e90610d96565b600480546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f22d1c35fe072d2e42c3c8f9bd4a0d34aa84a0101d020a62517b33fdb3174e5f791016104e8565b600b545f9060ff16156105935761058d82610ae7565b92915050565b60085460ff16156105a75761058d82610b45565b61058d82610b81565b5f546001600160a01b031633146105d95760405162461bcd60e51b815260040161038e90610d96565b6105e9633b9aca006103e8610e00565b81111561060957604051631e44fdeb60e11b815260040160405180910390fd5b60038190556040518181527f3336cd9708eaf2769a0f0dc0679f30e80f15dcd88d1921b5a16858e8b85c591a906020016103ec565b5f546001600160a01b031633146106675760405162461bcd60e51b815260040161038e90610d96565b6106705f610bc4565b565b5f546001600160a01b0316331461069b5760405162461bcd60e51b815260040161038e90610d96565b6106a9633b9aca0080610e00565b8111156106c95760405163874f603160e01b815260040160405180910390fd5b60068190556040518181527f2ab3f5a4ebbcbf3c24f62f5454f52f10e1a8c9dcc5acac8f19199ce881a6a108906020016103ec565b5f546001600160a01b031633146107275760405162461bcd60e51b815260040161038e90610d96565b60085460ff161561074b576040516379f9c57560e01b815260040160405180910390fd5b6008805460ff19166001179055565b5f546001600160a01b031633146107835760405162461bcd60e51b815260040161038e90610d96565b633b9aca008110806107a1575061079e633b9aca0080610e00565b81115b156107bf5760405163d9b5dcdf60e01b815260040160405180910390fd5b60098190556040518181527fd50d3079c77df569cd58d55d4e5614bfe7066449009425d22bde8e75242f50bb906020016103ec565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa15801561083b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061085f9190610dcd565b61087c576040516326b3506d60e11b815260040160405180910390fd5b60018190556040518181527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c44906020016103ec565b5f546001600160a01b031633146108da5760405162461bcd60e51b815260040161038e90610d96565b633b9aca008110806108f857506108f5633b9aca0080610e00565b81115b156109155760405162ae184360e01b815260040160405180910390fd5b600a8190556040518181527f8647cebb7e57360673a28415c0bed2f68c42a86c5035f1c9b2eda2b09509288a906020016103ec565b600b545f9060ff168061095f575060085460ff165b1561096b57505f919050565b61058d82610c13565b5f546001600160a01b0316331461099d5760405162461bcd60e51b815260040161038e90610d96565b6109ab633b9aca0080610e00565b8111156109cb5760405163f37ec21560e01b815260040160405180910390fd5b60078190556040518181527f6b332a036d8c3ead57dcb06c87243bd7a2aed015ddf2d0528c2501dae56331aa906020016103ec565b5f546001600160a01b03163314610a295760405162461bcd60e51b815260040161038e90610d96565b6001600160a01b038116610a7f5760405162461bcd60e51b815260206004820152601d60248201527f6e6577206f776e657220697320746865207a65726f2061646472657373000000604482015260640161038e565b610a8881610bc4565b50565b5f546001600160a01b03163314610ab45760405162461bcd60e51b815260040161038e90610d96565b600b5460ff1615610ad857604051631a7c228b60e21b815260040160405180910390fd5b600b805460ff19166001179055565b5f633b9aca0080600a548451600554600754610b039190610e00565b600154600654610b139190610e00565b610b1d9190610e17565b610b279190610e00565b610b319190610e00565b610b3b9190610e2a565b61058d9190610e2a565b5f633b9aca006005548351600754610b5d9190610e00565b610b679190610e00565b600154600654610b779190610e00565b610b3b9190610e17565b5f80610b8c83610c13565b90505f60015482610b9d9190610e00565b9050633b9aca0060035482610bb29190610e00565b610bbc9190610e2a565b949350505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80515f908190815b81811015610c6457848181518110610c3557610c35610e49565b01602001516001600160f81b0319165f03610c5557600483019250610c5c565b6010830192505b600101610c1b565b50506002540160400192915050565b5f60208284031215610c83575f80fd5b5035919050565b5f8060408385031215610c9b575f80fd5b50508035926020909101359150565b5f60208284031215610cba575f80fd5b81356001600160a01b0381168114610cd0575f80fd5b9392505050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215610cfb575f80fd5b813567ffffffffffffffff80821115610d12575f80fd5b818401915084601f830112610d25575f80fd5b813581811115610d3757610d37610cd7565b604051601f8201601f19908116603f01168101908382118183101715610d5f57610d5f610cd7565b81604052828152876020848701011115610d77575f80fd5b826020860160208301375f928101602001929092525095945050505050565b60208082526017908201527f63616c6c6572206973206e6f7420746865206f776e6572000000000000000000604082015260600190565b5f60208284031215610ddd575f80fd5b81518015158114610cd0575f80fd5b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761058d5761058d610dec565b8082018082111561058d5761058d610dec565b5f82610e4457634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffdfea164736f6c6343000818000a") ) // L2SystemConfig constants. From 393d6c1087ccc7ac13956cd102aed651dd20f60d Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Wed, 25 Jun 2025 04:20:03 +0800 Subject: [PATCH 10/23] address comments --- cmd/evm/internal/t8ntool/execution.go | 4 ++-- core/state_prefetcher.go | 2 +- core/state_processor.go | 2 +- core/tx_list.go | 2 +- core/tx_pool.go | 4 ++-- eth/state_accessor.go | 2 +- eth/tracers/api.go | 16 ++++++++-------- eth/tracers/api_test.go | 2 +- eth/tracers/internal/tracetest/calltrace_test.go | 6 +++--- eth/tracers/tracers_test.go | 2 +- les/state_accessor.go | 2 +- light/txpool.go | 2 +- rollup/fees/rollup_fee.go | 2 +- rollup/fees/rollup_fee_test.go | 2 -- rollup/tracing/tracing.go | 4 ++-- tests/state_test_util.go | 2 +- 16 files changed, 27 insertions(+), 29 deletions(-) diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index ff4d50810bc6..b5bfd2c417ea 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -184,9 +184,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, snapshot := statedb.Snapshot() evm := vm.NewEVM(vmContext, txContext, statedb, chainConfig, vmConfig) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) + l1DataFee, err := fees.CalculateRollupFee(tx, statedb, chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) if err != nil { - log.Info("rejected tx due to fees.CalculateL1DataFee", "index", i, "hash", tx.Hash(), "from", msg.From(), "error", err) + log.Info("rejected tx due to fees.CalculateRollupFee", "index", i, "hash", tx.Hash(), "from", msg.From(), "error", err) rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()}) continue } diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go index 5f31c0218516..1951ac0424ab 100644 --- a/core/state_prefetcher.go +++ b/core/state_prefetcher.go @@ -71,7 +71,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c } statedb.SetTxContext(tx.Hash(), i) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, p.config, block.Number(), block.Time()) + l1DataFee, err := fees.CalculateRollupFee(tx, statedb, p.config, block.Number(), block.Time()) if err != nil { return } diff --git a/core/state_processor.go b/core/state_processor.go index aea19a4e04c2..7bddb4ec36fc 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -135,7 +135,7 @@ func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainCon txContext := NewEVMTxContext(msg) evm.Reset(txContext, statedb) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, config, blockNumber, blockTime) + l1DataFee, err := fees.CalculateRollupFee(tx, statedb, config, blockNumber, blockTime) if err != nil { return nil, err } diff --git a/core/tx_list.go b/core/tx_list.go index fba3b57f0bed..4f794230f615 100644 --- a/core/tx_list.go +++ b/core/tx_list.go @@ -310,7 +310,7 @@ func (l *txList) Add(tx *types.Transaction, state *state.StateDB, priceBump uint l1DataFee := big.NewInt(0) if state != nil && chainconfig != nil { var err error - l1DataFee, err = fees.CalculateL1DataFee(tx, state, chainconfig, blockNumber, blockTime) + l1DataFee, err = fees.CalculateRollupFee(tx, state, chainconfig, blockNumber, blockTime) if err != nil { log.Error("Failed to calculate L1 data fee", "err", err, "tx", tx) return false, nil diff --git a/core/tx_pool.go b/core/tx_pool.go index 52f4b040d42c..5a58223c460f 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -839,7 +839,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { // 2. If FeeVault is enabled, perform an additional check for L1 data fees. if pool.chainconfig.Scroll.FeeVaultEnabled() { // Get L1 data fee in current state - l1DataFee, err := fees.CalculateL1DataFee(tx, pool.currentState, pool.chainconfig, pool.currentHead, pool.currentTime) + l1DataFee, err := fees.CalculateRollupFee(tx, pool.currentState, pool.chainconfig, pool.currentHead, pool.currentTime) if err != nil { return fmt.Errorf("failed to calculate L1 data fee, err: %w", err) } @@ -1692,7 +1692,7 @@ func (pool *TxPool) executableTxFilter(costLimit *big.Int) func(tx *types.Transa if pool.chainconfig.Scroll.FeeVaultEnabled() { // recheck L1 data fee, as the oracle price may have changed - l1DataFee, err := fees.CalculateL1DataFee(tx, pool.currentState, pool.chainconfig, pool.currentHead, pool.currentTime) + l1DataFee, err := fees.CalculateRollupFee(tx, pool.currentState, pool.chainconfig, pool.currentHead, pool.currentTime) if err != nil { log.Error("Failed to calculate L1 data fee", "err", err, "tx", tx) return false diff --git a/eth/state_accessor.go b/eth/state_accessor.go index f4a75fc59485..49426d7cae38 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -198,7 +198,7 @@ func (eth *Ethereum) stateAtTransaction(block *types.Block, txIndex int, reexec // Not yet the searched for transaction, execute on top of the current state vmenv := vm.NewEVM(context, txContext, statedb, eth.blockchain.Config(), vm.Config{}) statedb.SetTxContext(tx.Hash(), idx) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, eth.blockchain.Config(), block.Number(), block.Time()) + l1DataFee, err := fees.CalculateRollupFee(tx, statedb, eth.blockchain.Config(), block.Number(), block.Time()) if err != nil { return nil, vm.BlockContext{}, nil, err } diff --git a/eth/tracers/api.go b/eth/tracers/api.go index cdfa276cba25..548ee5b76359 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -292,11 +292,11 @@ func (api *API) traceChain(ctx context.Context, start, end *types.Block, config TxHash: tx.Hash(), } - l1DataFee, err := fees.CalculateL1DataFee(tx, task.statedb, api.backend.ChainConfig(), task.block.Number(), task.block.Time()) + l1DataFee, err := fees.CalculateRollupFee(tx, task.statedb, api.backend.ChainConfig(), task.block.Number(), task.block.Time()) if err != nil { // though it's not a "tracing error", we still need to put it here task.results[i] = &txTraceResult{Error: err.Error()} - log.Warn("CalculateL1DataFee failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err) + log.Warn("CalculateRollupFee failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err) break } @@ -557,9 +557,9 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config ) statedb.SetTxContext(tx.Hash(), i) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) + l1DataFee, err := fees.CalculateRollupFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) if err != nil { - log.Warn("Tracing intermediate roots did not complete due to fees.CalculateL1DataFee", "txindex", i, "txhash", tx.Hash(), "err", err) + log.Warn("Tracing intermediate roots did not complete due to fees.CalculateRollupFee", "txindex", i, "txhash", tx.Hash(), "err", err) return nil, err } @@ -645,7 +645,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac TxHash: txs[task.index].Hash(), } - l1DataFee, err := fees.CalculateL1DataFee(txs[task.index], task.statedb, api.backend.ChainConfig(), block.Number(), block.Time()) + l1DataFee, err := fees.CalculateRollupFee(txs[task.index], task.statedb, api.backend.ChainConfig(), block.Number(), block.Time()) if err != nil { // though it's not a "tracing error", we still need to put it here results[task.index] = &txTraceResult{ @@ -679,7 +679,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac msg, _ := tx.AsMessage(signer, block.BaseFee()) statedb.SetTxContext(tx.Hash(), i) vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, api.backend.ChainConfig(), vm.Config{}) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) + l1DataFee, err := fees.CalculateRollupFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) if err != nil { failed = err break @@ -804,7 +804,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block // Execute the transaction and flush any traces to disk vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf) statedb.SetTxContext(tx.Hash(), i) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) + l1DataFee, err := fees.CalculateRollupFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) if err == nil { _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()), l1DataFee) } @@ -869,7 +869,7 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config * TxIndex: int(index), TxHash: hash, } - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) + l1DataFee, err := fees.CalculateRollupFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) if err != nil { return nil, err } diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index 47b8b4c6ac9a..ce184f867176 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -173,7 +173,7 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block return msg, context, statedb, nil } vmenv := vm.NewEVM(context, txContext, statedb, b.chainConfig, vm.Config{}) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, b.chainConfig, block.Number(), block.Time()) + l1DataFee, err := fees.CalculateRollupFee(tx, statedb, b.chainConfig, block.Number(), block.Time()) if err != nil { return nil, vm.BlockContext{}, nil, err } diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go index 5ee8905fa46c..4ad134d32d62 100644 --- a/eth/tracers/internal/tracetest/calltrace_test.go +++ b/eth/tracers/internal/tracetest/calltrace_test.go @@ -193,7 +193,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) { if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, test.Genesis.Config, context.BlockNumber, context.Time.Uint64()) + l1DataFee, err := fees.CalculateRollupFee(tx, statedb, test.Genesis.Config, context.BlockNumber, context.Time.Uint64()) if err != nil { t.Fatalf("failed to calculate l1DataFee: %v", err) } @@ -308,7 +308,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) { } evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer}) snap := statedb.Snapshot() - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, test.Genesis.Config, context.BlockNumber, context.Time.Uint64()) + l1DataFee, err := fees.CalculateRollupFee(tx, statedb, test.Genesis.Config, context.BlockNumber, context.Time.Uint64()) if err != nil { b.Fatalf("failed to calculate l1DataFee: %v", err) } @@ -381,7 +381,7 @@ func TestZeroValueToNotExitCall(t *testing.T) { if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, params.MainnetChainConfig, context.BlockNumber, context.Time.Uint64()) + l1DataFee, err := fees.CalculateRollupFee(tx, statedb, params.MainnetChainConfig, context.BlockNumber, context.Time.Uint64()) if err != nil { t.Fatalf("failed to calculate l1DataFee: %v", err) } diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go index addd2b8cdb2a..4ee1bd0cb07f 100644 --- a/eth/tracers/tracers_test.go +++ b/eth/tracers/tracers_test.go @@ -112,7 +112,7 @@ func BenchmarkTransactionTrace(b *testing.B) { for i := 0; i < b.N; i++ { snap := statedb.Snapshot() - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, params.AllEthashProtocolChanges, context.BlockNumber, context.Time.Uint64()) + l1DataFee, err := fees.CalculateRollupFee(tx, statedb, params.AllEthashProtocolChanges, context.BlockNumber, context.Time.Uint64()) if err != nil { b.Fatal(err) } diff --git a/les/state_accessor.go b/les/state_accessor.go index b2afa28938cf..d5a005011256 100644 --- a/les/state_accessor.go +++ b/les/state_accessor.go @@ -65,7 +65,7 @@ func (leth *LightEthereum) stateAtTransaction(ctx context.Context, block *types. } // Not yet the searched for transaction, execute on top of the current state vmenv := vm.NewEVM(context, txContext, statedb, leth.blockchain.Config(), vm.Config{}) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, leth.blockchain.Config(), block.Number(), block.Time()) + l1DataFee, err := fees.CalculateRollupFee(tx, statedb, leth.blockchain.Config(), block.Number(), block.Time()) if err != nil { return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) } diff --git a/light/txpool.go b/light/txpool.go index e366fdc9639b..3ea7aa6611c4 100644 --- a/light/txpool.go +++ b/light/txpool.go @@ -410,7 +410,7 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error // 2. If FeeVault is enabled, perform an additional check for L1 data fees. if pool.config.Scroll.FeeVaultEnabled() { // Get L1 data fee in current state - l1DataFee, err := fees.CalculateL1DataFee(tx, currentState, pool.config, pool.currentHead, pool.currentTime) + l1DataFee, err := fees.CalculateRollupFee(tx, currentState, pool.config, pool.currentHead, pool.currentTime) if err != nil { return fmt.Errorf("failed to calculate L1 data fee, err: %w", err) } diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index c7fa36ad6510..741832386a75 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -267,7 +267,7 @@ func mulAndScale(x *big.Int, y *big.Int, precision *big.Int) *big.Int { return new(big.Int).Quo(z, precision) } -func CalculateL1DataFee(tx *types.Transaction, state StateDB, config *params.ChainConfig, blockNumber *big.Int, blockTime uint64) (*big.Int, error) { +func CalculateRollupFee(tx *types.Transaction, state StateDB, config *params.ChainConfig, blockNumber *big.Int, blockTime uint64) (*big.Int, error) { if tx.IsL1MessageTx() { return big.NewInt(0), nil } diff --git a/rollup/fees/rollup_fee_test.go b/rollup/fees/rollup_fee_test.go index 2fc3494067d6..b429686789bc 100644 --- a/rollup/fees/rollup_fee_test.go +++ b/rollup/fees/rollup_fee_test.go @@ -32,8 +32,6 @@ func TestL1DataFeeAfterCurie(t *testing.T) { assert.Equal(t, expected, actual) } func TestL1DataFeeFeynman(t *testing.T) { - // You may want to import rcfg in your test file - l1BaseFee := new(big.Int).SetInt64(1_000_000_000) l1BlobBaseFee := new(big.Int).SetInt64(1_000_000_000) execScalar := new(big.Int).SetInt64(10) diff --git a/rollup/tracing/tracing.go b/rollup/tracing/tracing.go index 0569a99bc475..34622d0b6a4a 100644 --- a/rollup/tracing/tracing.go +++ b/rollup/tracing/tracing.go @@ -239,7 +239,7 @@ func (env *TraceEnv) GetBlockTrace(block *types.Block) (*types.BlockTrace, error msg, _ := tx.AsMessage(env.signer, block.BaseFee()) env.state.SetTxContext(tx.Hash(), i) vmenv := vm.NewEVM(env.blockCtx, core.NewEVMTxContext(msg), env.state, env.chainConfig, vm.Config{}) - l1DataFee, err := fees.CalculateL1DataFee(tx, env.state, env.chainConfig, block.Number(), block.Time()) + l1DataFee, err := fees.CalculateRollupFee(tx, env.state, env.chainConfig, block.Number(), block.Time()) if err != nil { failed = err break @@ -342,7 +342,7 @@ func (env *TraceEnv) getTxResult(state *state.StateDB, index int, block *types.B state.SetTxContext(txctx.TxHash, txctx.TxIndex) // Computes the new state by applying the given message. - l1DataFee, err := fees.CalculateL1DataFee(tx, state, env.chainConfig, block.Number(), block.Time()) + l1DataFee, err := fees.CalculateRollupFee(tx, state, env.chainConfig, block.Number(), block.Time()) if err != nil { return err } diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 9f3a5da75a98..cb1f3244959c 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -251,7 +251,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh gaspool := new(core.GasPool) gaspool.AddGas(block.GasLimit()) - l1DataFee, err := fees.CalculateL1DataFee(&ttx, statedb, config, block.Number(), block.Time()) + l1DataFee, err := fees.CalculateRollupFee(&ttx, statedb, config, block.Number(), block.Time()) if err != nil { return nil, nil, common.Hash{}, err } From b93d2c11d704cd98552df079a5e319374cb7eeb8 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Wed, 25 Jun 2025 04:35:24 +0800 Subject: [PATCH 11/23] revert renaming CalculateL1DataFee to CalculateRollupFee --- cmd/evm/internal/t8ntool/execution.go | 4 ++-- core/state_prefetcher.go | 2 +- core/state_processor.go | 2 +- core/tx_list.go | 2 +- core/tx_pool.go | 4 ++-- eth/state_accessor.go | 2 +- eth/tracers/api.go | 16 ++++++++-------- eth/tracers/api_test.go | 2 +- eth/tracers/internal/tracetest/calltrace_test.go | 6 +++--- eth/tracers/tracers_test.go | 2 +- les/state_accessor.go | 2 +- light/txpool.go | 2 +- rollup/fees/rollup_fee.go | 2 +- rollup/tracing/tracing.go | 4 ++-- tests/state_test_util.go | 2 +- 15 files changed, 27 insertions(+), 27 deletions(-) diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index b5bfd2c417ea..ff4d50810bc6 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -184,9 +184,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, snapshot := statedb.Snapshot() evm := vm.NewEVM(vmContext, txContext, statedb, chainConfig, vmConfig) - l1DataFee, err := fees.CalculateRollupFee(tx, statedb, chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) if err != nil { - log.Info("rejected tx due to fees.CalculateRollupFee", "index", i, "hash", tx.Hash(), "from", msg.From(), "error", err) + log.Info("rejected tx due to fees.CalculateL1DataFee", "index", i, "hash", tx.Hash(), "from", msg.From(), "error", err) rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()}) continue } diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go index 1951ac0424ab..5f31c0218516 100644 --- a/core/state_prefetcher.go +++ b/core/state_prefetcher.go @@ -71,7 +71,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c } statedb.SetTxContext(tx.Hash(), i) - l1DataFee, err := fees.CalculateRollupFee(tx, statedb, p.config, block.Number(), block.Time()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, p.config, block.Number(), block.Time()) if err != nil { return } diff --git a/core/state_processor.go b/core/state_processor.go index 7bddb4ec36fc..aea19a4e04c2 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -135,7 +135,7 @@ func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainCon txContext := NewEVMTxContext(msg) evm.Reset(txContext, statedb) - l1DataFee, err := fees.CalculateRollupFee(tx, statedb, config, blockNumber, blockTime) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, config, blockNumber, blockTime) if err != nil { return nil, err } diff --git a/core/tx_list.go b/core/tx_list.go index 4f794230f615..fba3b57f0bed 100644 --- a/core/tx_list.go +++ b/core/tx_list.go @@ -310,7 +310,7 @@ func (l *txList) Add(tx *types.Transaction, state *state.StateDB, priceBump uint l1DataFee := big.NewInt(0) if state != nil && chainconfig != nil { var err error - l1DataFee, err = fees.CalculateRollupFee(tx, state, chainconfig, blockNumber, blockTime) + l1DataFee, err = fees.CalculateL1DataFee(tx, state, chainconfig, blockNumber, blockTime) if err != nil { log.Error("Failed to calculate L1 data fee", "err", err, "tx", tx) return false, nil diff --git a/core/tx_pool.go b/core/tx_pool.go index 5a58223c460f..52f4b040d42c 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -839,7 +839,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { // 2. If FeeVault is enabled, perform an additional check for L1 data fees. if pool.chainconfig.Scroll.FeeVaultEnabled() { // Get L1 data fee in current state - l1DataFee, err := fees.CalculateRollupFee(tx, pool.currentState, pool.chainconfig, pool.currentHead, pool.currentTime) + l1DataFee, err := fees.CalculateL1DataFee(tx, pool.currentState, pool.chainconfig, pool.currentHead, pool.currentTime) if err != nil { return fmt.Errorf("failed to calculate L1 data fee, err: %w", err) } @@ -1692,7 +1692,7 @@ func (pool *TxPool) executableTxFilter(costLimit *big.Int) func(tx *types.Transa if pool.chainconfig.Scroll.FeeVaultEnabled() { // recheck L1 data fee, as the oracle price may have changed - l1DataFee, err := fees.CalculateRollupFee(tx, pool.currentState, pool.chainconfig, pool.currentHead, pool.currentTime) + l1DataFee, err := fees.CalculateL1DataFee(tx, pool.currentState, pool.chainconfig, pool.currentHead, pool.currentTime) if err != nil { log.Error("Failed to calculate L1 data fee", "err", err, "tx", tx) return false diff --git a/eth/state_accessor.go b/eth/state_accessor.go index 49426d7cae38..f4a75fc59485 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -198,7 +198,7 @@ func (eth *Ethereum) stateAtTransaction(block *types.Block, txIndex int, reexec // Not yet the searched for transaction, execute on top of the current state vmenv := vm.NewEVM(context, txContext, statedb, eth.blockchain.Config(), vm.Config{}) statedb.SetTxContext(tx.Hash(), idx) - l1DataFee, err := fees.CalculateRollupFee(tx, statedb, eth.blockchain.Config(), block.Number(), block.Time()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, eth.blockchain.Config(), block.Number(), block.Time()) if err != nil { return nil, vm.BlockContext{}, nil, err } diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 548ee5b76359..cdfa276cba25 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -292,11 +292,11 @@ func (api *API) traceChain(ctx context.Context, start, end *types.Block, config TxHash: tx.Hash(), } - l1DataFee, err := fees.CalculateRollupFee(tx, task.statedb, api.backend.ChainConfig(), task.block.Number(), task.block.Time()) + l1DataFee, err := fees.CalculateL1DataFee(tx, task.statedb, api.backend.ChainConfig(), task.block.Number(), task.block.Time()) if err != nil { // though it's not a "tracing error", we still need to put it here task.results[i] = &txTraceResult{Error: err.Error()} - log.Warn("CalculateRollupFee failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err) + log.Warn("CalculateL1DataFee failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err) break } @@ -557,9 +557,9 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config ) statedb.SetTxContext(tx.Hash(), i) - l1DataFee, err := fees.CalculateRollupFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) if err != nil { - log.Warn("Tracing intermediate roots did not complete due to fees.CalculateRollupFee", "txindex", i, "txhash", tx.Hash(), "err", err) + log.Warn("Tracing intermediate roots did not complete due to fees.CalculateL1DataFee", "txindex", i, "txhash", tx.Hash(), "err", err) return nil, err } @@ -645,7 +645,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac TxHash: txs[task.index].Hash(), } - l1DataFee, err := fees.CalculateRollupFee(txs[task.index], task.statedb, api.backend.ChainConfig(), block.Number(), block.Time()) + l1DataFee, err := fees.CalculateL1DataFee(txs[task.index], task.statedb, api.backend.ChainConfig(), block.Number(), block.Time()) if err != nil { // though it's not a "tracing error", we still need to put it here results[task.index] = &txTraceResult{ @@ -679,7 +679,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac msg, _ := tx.AsMessage(signer, block.BaseFee()) statedb.SetTxContext(tx.Hash(), i) vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, api.backend.ChainConfig(), vm.Config{}) - l1DataFee, err := fees.CalculateRollupFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) if err != nil { failed = err break @@ -804,7 +804,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block // Execute the transaction and flush any traces to disk vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf) statedb.SetTxContext(tx.Hash(), i) - l1DataFee, err := fees.CalculateRollupFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) if err == nil { _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()), l1DataFee) } @@ -869,7 +869,7 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config * TxIndex: int(index), TxHash: hash, } - l1DataFee, err := fees.CalculateRollupFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number(), block.Time()) if err != nil { return nil, err } diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index ce184f867176..47b8b4c6ac9a 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -173,7 +173,7 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block return msg, context, statedb, nil } vmenv := vm.NewEVM(context, txContext, statedb, b.chainConfig, vm.Config{}) - l1DataFee, err := fees.CalculateRollupFee(tx, statedb, b.chainConfig, block.Number(), block.Time()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, b.chainConfig, block.Number(), block.Time()) if err != nil { return nil, vm.BlockContext{}, nil, err } diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go index 4ad134d32d62..5ee8905fa46c 100644 --- a/eth/tracers/internal/tracetest/calltrace_test.go +++ b/eth/tracers/internal/tracetest/calltrace_test.go @@ -193,7 +193,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) { if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } - l1DataFee, err := fees.CalculateRollupFee(tx, statedb, test.Genesis.Config, context.BlockNumber, context.Time.Uint64()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, test.Genesis.Config, context.BlockNumber, context.Time.Uint64()) if err != nil { t.Fatalf("failed to calculate l1DataFee: %v", err) } @@ -308,7 +308,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) { } evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer}) snap := statedb.Snapshot() - l1DataFee, err := fees.CalculateRollupFee(tx, statedb, test.Genesis.Config, context.BlockNumber, context.Time.Uint64()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, test.Genesis.Config, context.BlockNumber, context.Time.Uint64()) if err != nil { b.Fatalf("failed to calculate l1DataFee: %v", err) } @@ -381,7 +381,7 @@ func TestZeroValueToNotExitCall(t *testing.T) { if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } - l1DataFee, err := fees.CalculateRollupFee(tx, statedb, params.MainnetChainConfig, context.BlockNumber, context.Time.Uint64()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, params.MainnetChainConfig, context.BlockNumber, context.Time.Uint64()) if err != nil { t.Fatalf("failed to calculate l1DataFee: %v", err) } diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go index 4ee1bd0cb07f..addd2b8cdb2a 100644 --- a/eth/tracers/tracers_test.go +++ b/eth/tracers/tracers_test.go @@ -112,7 +112,7 @@ func BenchmarkTransactionTrace(b *testing.B) { for i := 0; i < b.N; i++ { snap := statedb.Snapshot() - l1DataFee, err := fees.CalculateRollupFee(tx, statedb, params.AllEthashProtocolChanges, context.BlockNumber, context.Time.Uint64()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, params.AllEthashProtocolChanges, context.BlockNumber, context.Time.Uint64()) if err != nil { b.Fatal(err) } diff --git a/les/state_accessor.go b/les/state_accessor.go index d5a005011256..b2afa28938cf 100644 --- a/les/state_accessor.go +++ b/les/state_accessor.go @@ -65,7 +65,7 @@ func (leth *LightEthereum) stateAtTransaction(ctx context.Context, block *types. } // Not yet the searched for transaction, execute on top of the current state vmenv := vm.NewEVM(context, txContext, statedb, leth.blockchain.Config(), vm.Config{}) - l1DataFee, err := fees.CalculateRollupFee(tx, statedb, leth.blockchain.Config(), block.Number(), block.Time()) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, leth.blockchain.Config(), block.Number(), block.Time()) if err != nil { return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) } diff --git a/light/txpool.go b/light/txpool.go index 3ea7aa6611c4..e366fdc9639b 100644 --- a/light/txpool.go +++ b/light/txpool.go @@ -410,7 +410,7 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error // 2. If FeeVault is enabled, perform an additional check for L1 data fees. if pool.config.Scroll.FeeVaultEnabled() { // Get L1 data fee in current state - l1DataFee, err := fees.CalculateRollupFee(tx, currentState, pool.config, pool.currentHead, pool.currentTime) + l1DataFee, err := fees.CalculateL1DataFee(tx, currentState, pool.config, pool.currentHead, pool.currentTime) if err != nil { return fmt.Errorf("failed to calculate L1 data fee, err: %w", err) } diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index 741832386a75..c7fa36ad6510 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -267,7 +267,7 @@ func mulAndScale(x *big.Int, y *big.Int, precision *big.Int) *big.Int { return new(big.Int).Quo(z, precision) } -func CalculateRollupFee(tx *types.Transaction, state StateDB, config *params.ChainConfig, blockNumber *big.Int, blockTime uint64) (*big.Int, error) { +func CalculateL1DataFee(tx *types.Transaction, state StateDB, config *params.ChainConfig, blockNumber *big.Int, blockTime uint64) (*big.Int, error) { if tx.IsL1MessageTx() { return big.NewInt(0), nil } diff --git a/rollup/tracing/tracing.go b/rollup/tracing/tracing.go index 34622d0b6a4a..0569a99bc475 100644 --- a/rollup/tracing/tracing.go +++ b/rollup/tracing/tracing.go @@ -239,7 +239,7 @@ func (env *TraceEnv) GetBlockTrace(block *types.Block) (*types.BlockTrace, error msg, _ := tx.AsMessage(env.signer, block.BaseFee()) env.state.SetTxContext(tx.Hash(), i) vmenv := vm.NewEVM(env.blockCtx, core.NewEVMTxContext(msg), env.state, env.chainConfig, vm.Config{}) - l1DataFee, err := fees.CalculateRollupFee(tx, env.state, env.chainConfig, block.Number(), block.Time()) + l1DataFee, err := fees.CalculateL1DataFee(tx, env.state, env.chainConfig, block.Number(), block.Time()) if err != nil { failed = err break @@ -342,7 +342,7 @@ func (env *TraceEnv) getTxResult(state *state.StateDB, index int, block *types.B state.SetTxContext(txctx.TxHash, txctx.TxIndex) // Computes the new state by applying the given message. - l1DataFee, err := fees.CalculateRollupFee(tx, state, env.chainConfig, block.Number(), block.Time()) + l1DataFee, err := fees.CalculateL1DataFee(tx, state, env.chainConfig, block.Number(), block.Time()) if err != nil { return err } diff --git a/tests/state_test_util.go b/tests/state_test_util.go index cb1f3244959c..9f3a5da75a98 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -251,7 +251,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh gaspool := new(core.GasPool) gaspool.AddGas(block.GasLimit()) - l1DataFee, err := fees.CalculateRollupFee(&ttx, statedb, config, block.Number(), block.Time()) + l1DataFee, err := fees.CalculateL1DataFee(&ttx, statedb, config, block.Number(), block.Time()) if err != nil { return nil, nil, common.Hash{}, err } From 980836503e14c88bdbba75f9e82a59dd970decab Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Wed, 25 Jun 2025 04:40:09 +0800 Subject: [PATCH 12/23] simplify EstimateL1DataFeeForMessage --- rollup/fees/rollup_fee.go | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index c7fa36ad6510..63a4bf00b76c 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -74,24 +74,7 @@ func EstimateL1DataFeeForMessage(msg Message, baseFee *big.Int, config *params.C return nil, err } - raw, err := tx.MarshalBinary() - if err != nil { - return nil, err - } - - gpoState := readGPOStorageSlots(rcfg.L1GasPriceOracleAddress, state) - - var rollupFee *big.Int - - if !config.IsCurie(blockNumber) { - rollupFee = calculateEncodedL1DataFee(raw, gpoState.overhead, gpoState.l1BaseFee, gpoState.scalar) - } else if !config.IsFeynman(blockTime) { - rollupFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) - } else { - rollupFee = calculateEncodedL1DataFeeFeynman(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) - } - - return rollupFee, nil + return CalculateL1DataFee(tx, state, config, blockNumber, blockTime) } // asUnsignedTx turns a Message into a types.Transaction From 3156b0247e2f0f46025c84aab64764b24bf92241 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Wed, 25 Jun 2025 04:46:55 +0800 Subject: [PATCH 13/23] address comments --- rollup/fees/rollup_fee.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index 63a4bf00b76c..317b8ff2d799 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -186,11 +186,24 @@ func calculateEncodedL1DataFeeCurie(data []byte, l1BaseFee *big.Int, l1BlobBaseF } // calculateEncodedL1DataFeeFeynman computes the L1 fee for an RLP-encoded tx, post Feynman +// +// Post Feynman formula: +// rollup_fee(tx) = est_compression_ratio(tx) * tx_size * ( +// +// exec_scalar * l1_base_fee + +// blob_scalar * l1_blob_base_fee +// +// ) +// +// Where: +// - est_compression_ratio(tx) = 1 (placeholder for future implementation) +// - exec_scalar = compression_scalar + commit_scalar + verification_scalar +// - blob_scalar = compression_scalar + blob_scalar func calculateEncodedL1DataFeeFeynman( data []byte, l1BaseFee *big.Int, l1BlobBaseFee *big.Int, - execScalar *big.Int, + commitScalar *big.Int, blobScalar *big.Int, ) *big.Int { // tx size (RLP-encoded) @@ -200,7 +213,7 @@ func calculateEncodedL1DataFeeFeynman( compressionRatio := big.NewInt(rcfg.Precision.Int64()) // compute gas components - execGas := new(big.Int).Mul(execScalar, l1BaseFee) + execGas := new(big.Int).Mul(commitScalar, l1BaseFee) blobGas := new(big.Int).Mul(blobScalar, l1BlobBaseFee) // fee per byte = execGas + blobGas From 5039d30a31cc61f763f0c790ab276370b3c37f01 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Wed, 25 Jun 2025 05:22:39 +0800 Subject: [PATCH 14/23] add a comment based on pr reviews --- rollup/fees/rollup_fee.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index 317b8ff2d799..a392c95c1fdf 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -203,7 +203,7 @@ func calculateEncodedL1DataFeeFeynman( data []byte, l1BaseFee *big.Int, l1BlobBaseFee *big.Int, - commitScalar *big.Int, + execScalar *big.Int, blobScalar *big.Int, ) *big.Int { // tx size (RLP-encoded) @@ -213,7 +213,7 @@ func calculateEncodedL1DataFeeFeynman( compressionRatio := big.NewInt(rcfg.Precision.Int64()) // compute gas components - execGas := new(big.Int).Mul(commitScalar, l1BaseFee) + execGas := new(big.Int).Mul(execScalar, l1BaseFee) blobGas := new(big.Int).Mul(blobScalar, l1BlobBaseFee) // fee per byte = execGas + blobGas @@ -282,6 +282,7 @@ func CalculateL1DataFee(tx *types.Transaction, state StateDB, config *params.Cha } else if !config.IsFeynman(blockTime) { l1DataFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) } else { + // The contract slot for commitScalar is changed to execScalar in Feynman l1DataFee = calculateEncodedL1DataFeeFeynman(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) } From 7d7a9b605ecbd12dd55d6bc19695e56d6274b44b Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Wed, 25 Jun 2025 05:39:04 +0800 Subject: [PATCH 15/23] update formula --- rollup/fees/rollup_fee.go | 80 ++++++++++++++++++++++++---------- rollup/fees/rollup_fee_test.go | 62 ++++++++++++++++++++------ 2 files changed, 104 insertions(+), 38 deletions(-) diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index a392c95c1fdf..a31e8de4ced2 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -54,12 +54,14 @@ type StateDB interface { } type gpoState struct { - l1BaseFee *big.Int - overhead *big.Int - scalar *big.Int - l1BlobBaseFee *big.Int - commitScalar *big.Int - blobScalar *big.Int + l1BaseFee *big.Int + overhead *big.Int + scalar *big.Int + l1BlobBaseFee *big.Int + commitScalar *big.Int + blobScalar *big.Int + penaltyThreshold *big.Int + penaltyFactor *big.Int } func EstimateL1DataFeeForMessage(msg Message, baseFee *big.Int, config *params.ChainConfig, signer types.Signer, state StateDB, blockNumber *big.Int, blockTime uint64) (*big.Int, error) { @@ -158,9 +160,29 @@ func readGPOStorageSlots(addr common.Address, state StateDB) gpoState { gpoState.l1BlobBaseFee = state.GetState(addr, rcfg.L1BlobBaseFeeSlot).Big() gpoState.commitScalar = state.GetState(addr, rcfg.CommitScalarSlot).Big() gpoState.blobScalar = state.GetState(addr, rcfg.BlobScalarSlot).Big() + gpoState.penaltyThreshold = state.GetState(addr, rcfg.PenaltyThresholdSlot).Big() + gpoState.penaltyFactor = state.GetState(addr, rcfg.PenaltyFactorSlot).Big() return gpoState } +// calculateCompressionRatio computes the compression ratio of the data using zstd +// compression_ratio(tx) = size(tx) * PRECISION / size(zstd(tx)) +func calculateCompressionRatio(data []byte) *big.Int { + // FIXME: This is a placeholder for the actual compression ratio calculation in another PR. + return big.NewInt(1_000_000_000) // 1 * PRECISION +} + +// calculatePenalty computes the penalty multiplier based on compression ratio +// penalty(tx) = compression_ratio(tx) >= penalty_threshold ? 1 * PRECISION : penalty_factor +func calculatePenalty(compressionRatio, penaltyThreshold, penaltyFactor *big.Int) *big.Int { + if compressionRatio.Cmp(penaltyThreshold) >= 0 { + // No penalty + return new(big.Int).Set(rcfg.Precision) + } + // Apply penalty + return new(big.Int).Set(penaltyFactor) +} + // calculateEncodedL1DataFee computes the L1 fee for an RLP-encoded tx func calculateEncodedL1DataFee(data []byte, overhead, l1BaseFee *big.Int, scalar *big.Int) *big.Int { l1GasUsed := calculateL1GasUsed(data, overhead) @@ -188,40 +210,42 @@ func calculateEncodedL1DataFeeCurie(data []byte, l1BaseFee *big.Int, l1BlobBaseF // calculateEncodedL1DataFeeFeynman computes the L1 fee for an RLP-encoded tx, post Feynman // // Post Feynman formula: -// rollup_fee(tx) = est_compression_ratio(tx) * tx_size * ( -// -// exec_scalar * l1_base_fee + -// blob_scalar * l1_blob_base_fee -// -// ) +// rollup_fee(tx) = (execScalar * l1BaseFee + blobScalar * l1BlobBaseFee) * size(tx) * penalty(tx) / PRECISION / PRECISION // // Where: -// - est_compression_ratio(tx) = 1 (placeholder for future implementation) -// - exec_scalar = compression_scalar + commit_scalar + verification_scalar -// - blob_scalar = compression_scalar + blob_scalar +// penalty(tx) = compression_ratio(tx) >= penalty_threshold ? 1 * PRECISION : penalty_factor +// +// compression_ratio(tx) = size(tx) * PRECISION / size(zstd(tx)) +// exec_scalar = compression_scalar * (commit_scalar + verification_scalar) +// blob_scalar = compression_scalar * blob_scalar func calculateEncodedL1DataFeeFeynman( data []byte, l1BaseFee *big.Int, l1BlobBaseFee *big.Int, execScalar *big.Int, blobScalar *big.Int, + penaltyThreshold *big.Int, + penaltyFactor *big.Int, ) *big.Int { - // tx size (RLP-encoded) - txSize := big.NewInt(int64(len(data))) + // Calculate compression ratio + compressionRatio := calculateCompressionRatio(data) - // compression_ratio(tx) = 1 (placeholder, scaled to match scalars precision) - compressionRatio := big.NewInt(rcfg.Precision.Int64()) + // Calculate penalty multiplier + penalty := calculatePenalty(compressionRatio, penaltyThreshold, penaltyFactor) + + // Transaction size (RLP-encoded) + txSize := big.NewInt(int64(len(data))) - // compute gas components + // Compute gas components execGas := new(big.Int).Mul(execScalar, l1BaseFee) blobGas := new(big.Int).Mul(blobScalar, l1BlobBaseFee) // fee per byte = execGas + blobGas feePerByte := new(big.Int).Add(execGas, blobGas) - // l1DataFee = compression_ratio * tx_size * feePerByte - l1DataFee := new(big.Int).Mul(compressionRatio, txSize) - l1DataFee.Mul(l1DataFee, feePerByte) + // l1DataFee = feePerByte * txSize * penalty + l1DataFee := new(big.Int).Mul(feePerByte, txSize) + l1DataFee.Mul(l1DataFee, penalty) // Divide by rcfg.Precision (once for ratio, once for scalar) l1DataFee.Div(l1DataFee, rcfg.Precision) @@ -283,7 +307,15 @@ func CalculateL1DataFee(tx *types.Transaction, state StateDB, config *params.Cha l1DataFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) } else { // The contract slot for commitScalar is changed to execScalar in Feynman - l1DataFee = calculateEncodedL1DataFeeFeynman(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) + l1DataFee = calculateEncodedL1DataFeeFeynman( + raw, + gpoState.l1BaseFee, + gpoState.l1BlobBaseFee, + gpoState.commitScalar, // now represents execScalar + gpoState.blobScalar, + gpoState.penaltyThreshold, + gpoState.penaltyFactor, + ) } // ensure l1DataFee fits into uint64 for circuit compatibility diff --git a/rollup/fees/rollup_fee_test.go b/rollup/fees/rollup_fee_test.go index b429686789bc..782b51ccda36 100644 --- a/rollup/fees/rollup_fee_test.go +++ b/rollup/fees/rollup_fee_test.go @@ -36,22 +36,56 @@ func TestL1DataFeeFeynman(t *testing.T) { l1BlobBaseFee := new(big.Int).SetInt64(1_000_000_000) execScalar := new(big.Int).SetInt64(10) blobScalar := new(big.Int).SetInt64(20) - data := make([]byte, 10) // txSize = 10 + penaltyThreshold := new(big.Int).SetInt64(1_000_000_000) // 1 * PRECISION + penaltyFactor := new(big.Int).SetInt64(2_000_000_000) // 2 * PRECISION (200% penalty) - // feePerByte = execScalar * l1BaseFee + blobScalar * l1BlobBaseFee = 10_000_000_000 + 20_000_000_000 = 30_000_000_000 - // l1DataFee = precision * txSize * feePerByte / precision / precision - // = 1_000_000_000 * 10 * 30_000_000_000 / 1_000_000_000 / 1_000_000 = 300_000_000_000_000_000 / 1_000_000_000 / 1_000_000_000 = 300 - //TODO for now compression_ratio = precision, placeholder + // Test case 1: No penalty (compression ratio >= threshold) + t.Run("no penalty case", func(t *testing.T) { + data := make([]byte, 10) // txSize = 10 - expected := new(big.Int).SetInt64(300) + // Since compression ratio will be >= penaltyThreshold, penalty = 1 * PRECISION + // feePerByte = execScalar * l1BaseFee + blobScalar * l1BlobBaseFee = 10 * 1_000_000_000 + 20 * 1_000_000_000 = 30_000_000_000 + // l1DataFee = feePerByte * txSize * penalty / PRECISION / PRECISION + // = 30_000_000_000 * 10 * 1_000_000_000 / 1_000_000_000 / 1_000_000_000 = 300 - actual := calculateEncodedL1DataFeeFeynman( - data, - l1BaseFee, - l1BlobBaseFee, - execScalar, - blobScalar, - ) + expected := new(big.Int).SetInt64(300) - assert.Equal(t, expected, actual) + actual := calculateEncodedL1DataFeeFeynman( + data, + l1BaseFee, + l1BlobBaseFee, + execScalar, + blobScalar, + penaltyThreshold, + penaltyFactor, + ) + + assert.Equal(t, expected, actual) + }) + + // Test case 2: With penalty (compression ratio < threshold) + t.Run("with penalty case", func(t *testing.T) { + data := make([]byte, 100) // txSize = 100 + + // Set a high penalty threshold to force penalty application + highPenaltyThreshold := new(big.Int).SetInt64(1000_000_000_000) // 1000 * PRECISION + + // feePerByte = execScalar * l1BaseFee + blobScalar * l1BlobBaseFee = 30_000_000_000 + // l1DataFee = feePerByte * txSize * penaltyFactor / PRECISION / PRECISION + // = 30_000_000_000 * 100 * 2_000_000_000 / 1_000_000_000 / 1_000_000_000 = 6000 + + expected := new(big.Int).SetInt64(6000) + + actual := calculateEncodedL1DataFeeFeynman( + data, + l1BaseFee, + l1BlobBaseFee, + execScalar, + blobScalar, + highPenaltyThreshold, + penaltyFactor, + ) + + assert.Equal(t, expected, actual) + }) } From a36f63c01e83114b0682741ac7fb9a3141de5101 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Wed, 25 Jun 2025 06:08:36 +0800 Subject: [PATCH 16/23] tweaks --- rollup/fees/rollup_fee.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index a31e8de4ced2..e88071564f66 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -169,7 +169,7 @@ func readGPOStorageSlots(addr common.Address, state StateDB) gpoState { // compression_ratio(tx) = size(tx) * PRECISION / size(zstd(tx)) func calculateCompressionRatio(data []byte) *big.Int { // FIXME: This is a placeholder for the actual compression ratio calculation in another PR. - return big.NewInt(1_000_000_000) // 1 * PRECISION + return rcfg.Precision } // calculatePenalty computes the penalty multiplier based on compression ratio @@ -177,10 +177,10 @@ func calculateCompressionRatio(data []byte) *big.Int { func calculatePenalty(compressionRatio, penaltyThreshold, penaltyFactor *big.Int) *big.Int { if compressionRatio.Cmp(penaltyThreshold) >= 0 { // No penalty - return new(big.Int).Set(rcfg.Precision) + return rcfg.Precision } // Apply penalty - return new(big.Int).Set(penaltyFactor) + return penaltyFactor } // calculateEncodedL1DataFee computes the L1 fee for an RLP-encoded tx From b621be4eea4f9e7859848fe27c94f08448067fd7 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Wed, 25 Jun 2025 17:40:44 +0800 Subject: [PATCH 17/23] tweak comments --- rollup/fees/rollup_fee.go | 6 +++--- rollup/fees/rollup_fee_test.go | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index e88071564f66..6ea0feb50647 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -247,9 +247,9 @@ func calculateEncodedL1DataFeeFeynman( l1DataFee := new(big.Int).Mul(feePerByte, txSize) l1DataFee.Mul(l1DataFee, penalty) - // Divide by rcfg.Precision (once for ratio, once for scalar) - l1DataFee.Div(l1DataFee, rcfg.Precision) - l1DataFee.Div(l1DataFee, rcfg.Precision) + // Divide by rcfg.Precision (once for scalars, once for penalty) + l1DataFee.Div(l1DataFee, rcfg.Precision) // account for scalars + l1DataFee.Div(l1DataFee, rcfg.Precision) // accounts for penalty return l1DataFee } diff --git a/rollup/fees/rollup_fee_test.go b/rollup/fees/rollup_fee_test.go index 782b51ccda36..21c901795cc7 100644 --- a/rollup/fees/rollup_fee_test.go +++ b/rollup/fees/rollup_fee_test.go @@ -31,6 +31,7 @@ func TestL1DataFeeAfterCurie(t *testing.T) { actual := calculateEncodedL1DataFeeCurie(data, l1BaseFee, l1BlobBaseFee, commitScalar, blobScalar) assert.Equal(t, expected, actual) } + func TestL1DataFeeFeynman(t *testing.T) { l1BaseFee := new(big.Int).SetInt64(1_000_000_000) l1BlobBaseFee := new(big.Int).SetInt64(1_000_000_000) From 872ccf59c2d2e3c50dff67df6b830d53b84325e0 Mon Sep 17 00:00:00 2001 From: Alejandro Ranchal-Pedrosa Date: Wed, 25 Jun 2025 12:17:56 +0200 Subject: [PATCH 18/23] Estimate compression ratio at rollupFee for Feynman (#1197) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Estimate compression ratio * Update rollup/fees/rollup_fee.go Co-authored-by: Péter Garamvölgyi * Check compressed size smaller and remove unnecessary checks/changes * goimports locally run * rollback format changes * update da-codec's zstd function * apply zstd * tweaks * tweak unit test * make sure compression ratio >= 1 * nit --------- Co-authored-by: Péter Garamvölgyi Co-authored-by: colinlyguo Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- rollup/fees/rollup_fee.go | 34 ++++++++++++++++++++++++++++++++-- rollup/fees/rollup_fee_test.go | 8 ++++---- 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index ca5088a456fb..2ecfa287bc43 100644 --- a/go.mod +++ b/go.mod @@ -51,7 +51,7 @@ require ( github.com/prometheus/tsdb v0.7.1 github.com/rjeczalik/notify v0.9.1 github.com/rs/cors v1.7.0 - github.com/scroll-tech/da-codec v0.1.3-0.20250519114140-bfa7133d4ad1 + github.com/scroll-tech/da-codec v0.1.3-0.20250623141222-9e6ea1d439fa github.com/scroll-tech/zktrie v0.8.4 github.com/shirou/gopsutil v3.21.11+incompatible github.com/sourcegraph/conc v0.3.0 diff --git a/go.sum b/go.sum index d13a6b3db16c..c29ed73f744f 100644 --- a/go.sum +++ b/go.sum @@ -396,8 +396,8 @@ github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncj github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/scroll-tech/da-codec v0.1.3-0.20250519114140-bfa7133d4ad1 h1:6aKqJSal+QVdB5HMWMs0JTbAIZ6/iAHJx9qizz0w9dU= -github.com/scroll-tech/da-codec v0.1.3-0.20250519114140-bfa7133d4ad1/go.mod h1:yhTS9OVC0xQGhg7DN5iV5KZJvnSIlFWAxDdp+6jxQtY= +github.com/scroll-tech/da-codec v0.1.3-0.20250623141222-9e6ea1d439fa h1:IwobY81o8LeI1kV4WkbaYFh6oDtAfheFjUO/dapkNlE= +github.com/scroll-tech/da-codec v0.1.3-0.20250623141222-9e6ea1d439fa/go.mod h1:T+370kLxwACnmWaq4rgtKGyLCd7QSE6iy0JLfCp1qj4= github.com/scroll-tech/zktrie v0.8.4 h1:UagmnZ4Z3ITCk+aUq9NQZJNAwnWl4gSxsLb2Nl7IgRE= github.com/scroll-tech/zktrie v0.8.4/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk= github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index 6ea0feb50647..9f8f36dea043 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -6,10 +6,12 @@ import ( "math/big" "github.com/holiman/uint256" + "github.com/scroll-tech/da-codec/encoding/zstd" "github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/crypto" + "github.com/scroll-tech/go-ethereum/log" "github.com/scroll-tech/go-ethereum/params" "github.com/scroll-tech/go-ethereum/rollup/rcfg" ) @@ -168,8 +170,36 @@ func readGPOStorageSlots(addr common.Address, state StateDB) gpoState { // calculateCompressionRatio computes the compression ratio of the data using zstd // compression_ratio(tx) = size(tx) * PRECISION / size(zstd(tx)) func calculateCompressionRatio(data []byte) *big.Int { - // FIXME: This is a placeholder for the actual compression ratio calculation in another PR. - return rcfg.Precision + if len(data) == 0 { + return rcfg.Precision + } + + // Compress data using zstd + compressed, err := zstd.CompressScrollBatchBytesStandard(data) + if err != nil { + log.Error("Batch compression failed, using 1.0 compression ratio", "error", err, "data size", len(data), "data", common.Bytes2Hex(data)) + } + + if len(compressed) == 0 { + log.Error("Compressed data is empty, using 1.0 compression ratio", "data size", len(data), "data", common.Bytes2Hex(data)) + return rcfg.Precision + } + + // compression_ratio = size(tx) * PRECISION / size(zstd(tx)) + originalSize := new(big.Int).SetUint64(uint64(len(data))) + compressedSize := new(big.Int).SetUint64(uint64(len(compressed))) + + // Make sure compression ratio >= 1 by checking if compressed data is bigger or equal to original data + // This behavior is consistent with DA Batch compression in codecv7 and later versions + if len(compressed) >= len(data) { + log.Debug("Compressed data is bigger or equal to the original data, using 1.0 compression ratio", "original size", len(data), "compressed size", len(compressed)) + return rcfg.Precision + } + + ratio := new(big.Int).Mul(originalSize, rcfg.Precision) + ratio.Div(ratio, compressedSize) + + return ratio } // calculatePenalty computes the penalty multiplier based on compression ratio diff --git a/rollup/fees/rollup_fee_test.go b/rollup/fees/rollup_fee_test.go index 21c901795cc7..306e5d012a36 100644 --- a/rollup/fees/rollup_fee_test.go +++ b/rollup/fees/rollup_fee_test.go @@ -37,19 +37,19 @@ func TestL1DataFeeFeynman(t *testing.T) { l1BlobBaseFee := new(big.Int).SetInt64(1_000_000_000) execScalar := new(big.Int).SetInt64(10) blobScalar := new(big.Int).SetInt64(20) - penaltyThreshold := new(big.Int).SetInt64(1_000_000_000) // 1 * PRECISION + penaltyThreshold := new(big.Int).SetInt64(6_000_000_000) // 6 * PRECISION penaltyFactor := new(big.Int).SetInt64(2_000_000_000) // 2 * PRECISION (200% penalty) // Test case 1: No penalty (compression ratio >= threshold) t.Run("no penalty case", func(t *testing.T) { - data := make([]byte, 10) // txSize = 10 + data := make([]byte, 100) // txSize = 100 // Since compression ratio will be >= penaltyThreshold, penalty = 1 * PRECISION // feePerByte = execScalar * l1BaseFee + blobScalar * l1BlobBaseFee = 10 * 1_000_000_000 + 20 * 1_000_000_000 = 30_000_000_000 // l1DataFee = feePerByte * txSize * penalty / PRECISION / PRECISION - // = 30_000_000_000 * 10 * 1_000_000_000 / 1_000_000_000 / 1_000_000_000 = 300 + // = 30_000_000_000 * 100 * 1_000_000_000 / 1_000_000_000 / 1_000_000_000 = 3000 - expected := new(big.Int).SetInt64(300) + expected := new(big.Int).SetInt64(3000) actual := calculateEncodedL1DataFeeFeynman( data, From 1fbe3eab3e32e573bea43cd5f8d4e40d8a3a651d Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Wed, 25 Jun 2025 18:52:43 +0800 Subject: [PATCH 19/23] refactoring --- go.mod | 2 +- go.sum | 4 +-- rollup/fees/rollup_fee.go | 19 ++++++----- rollup/fees/rollup_fee_test.go | 61 ++++++++++++++++++++++++++++++---- 4 files changed, 68 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 2ecfa287bc43..e62aaf5349d1 100644 --- a/go.mod +++ b/go.mod @@ -51,7 +51,7 @@ require ( github.com/prometheus/tsdb v0.7.1 github.com/rjeczalik/notify v0.9.1 github.com/rs/cors v1.7.0 - github.com/scroll-tech/da-codec v0.1.3-0.20250623141222-9e6ea1d439fa + github.com/scroll-tech/da-codec v0.1.3-0.20250625104355-9592886c0145 github.com/scroll-tech/zktrie v0.8.4 github.com/shirou/gopsutil v3.21.11+incompatible github.com/sourcegraph/conc v0.3.0 diff --git a/go.sum b/go.sum index c29ed73f744f..f36a3a0781ca 100644 --- a/go.sum +++ b/go.sum @@ -396,8 +396,8 @@ github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncj github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/scroll-tech/da-codec v0.1.3-0.20250623141222-9e6ea1d439fa h1:IwobY81o8LeI1kV4WkbaYFh6oDtAfheFjUO/dapkNlE= -github.com/scroll-tech/da-codec v0.1.3-0.20250623141222-9e6ea1d439fa/go.mod h1:T+370kLxwACnmWaq4rgtKGyLCd7QSE6iy0JLfCp1qj4= +github.com/scroll-tech/da-codec v0.1.3-0.20250625104355-9592886c0145 h1:dQQf/V7lYPWALJHAC7wdWtLrbX8j2E+cxzZyoPNeGDQ= +github.com/scroll-tech/da-codec v0.1.3-0.20250625104355-9592886c0145/go.mod h1:T+370kLxwACnmWaq4rgtKGyLCd7QSE6iy0JLfCp1qj4= github.com/scroll-tech/zktrie v0.8.4 h1:UagmnZ4Z3ITCk+aUq9NQZJNAwnWl4gSxsLb2Nl7IgRE= github.com/scroll-tech/zktrie v0.8.4/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk= github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index 9f8f36dea043..51bdd24af6da 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -6,7 +6,7 @@ import ( "math/big" "github.com/holiman/uint256" - "github.com/scroll-tech/da-codec/encoding/zstd" + "github.com/scroll-tech/da-codec/encoding" "github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/core/types" @@ -167,17 +167,18 @@ func readGPOStorageSlots(addr common.Address, state StateDB) gpoState { return gpoState } -// calculateCompressionRatio computes the compression ratio of the data using zstd +// estimateTxCompressionRatio estimates the compression ratio for transaction data using da-codec // compression_ratio(tx) = size(tx) * PRECISION / size(zstd(tx)) -func calculateCompressionRatio(data []byte) *big.Int { +func estimateTxCompressionRatio(data []byte, blockNumber uint64, blockTime uint64, config *params.ChainConfig) *big.Int { if len(data) == 0 { return rcfg.Precision } - // Compress data using zstd - compressed, err := zstd.CompressScrollBatchBytesStandard(data) + // Compress data using da-codec + compressed, err := encoding.CompressScrollBatchBytes(data, blockNumber, blockTime, config) if err != nil { log.Error("Batch compression failed, using 1.0 compression ratio", "error", err, "data size", len(data), "data", common.Bytes2Hex(data)) + return rcfg.Precision } if len(compressed) == 0 { @@ -256,10 +257,8 @@ func calculateEncodedL1DataFeeFeynman( blobScalar *big.Int, penaltyThreshold *big.Int, penaltyFactor *big.Int, + compressionRatio *big.Int, ) *big.Int { - // Calculate compression ratio - compressionRatio := calculateCompressionRatio(data) - // Calculate penalty multiplier penalty := calculatePenalty(compressionRatio, penaltyThreshold, penaltyFactor) @@ -336,6 +335,9 @@ func CalculateL1DataFee(tx *types.Transaction, state StateDB, config *params.Cha } else if !config.IsFeynman(blockTime) { l1DataFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) } else { + // Calculate compression ratio for Feynman + compressionRatio := estimateTxCompressionRatio(raw, blockNumber.Uint64(), blockTime, config) + // The contract slot for commitScalar is changed to execScalar in Feynman l1DataFee = calculateEncodedL1DataFeeFeynman( raw, @@ -345,6 +347,7 @@ func CalculateL1DataFee(tx *types.Transaction, state StateDB, config *params.Cha gpoState.blobScalar, gpoState.penaltyThreshold, gpoState.penaltyFactor, + compressionRatio, ) } diff --git a/rollup/fees/rollup_fee_test.go b/rollup/fees/rollup_fee_test.go index 306e5d012a36..5dd96e3cf053 100644 --- a/rollup/fees/rollup_fee_test.go +++ b/rollup/fees/rollup_fee_test.go @@ -5,6 +5,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "github.com/scroll-tech/go-ethereum/params" ) func TestL1DataFeeBeforeCurie(t *testing.T) { @@ -42,9 +44,10 @@ func TestL1DataFeeFeynman(t *testing.T) { // Test case 1: No penalty (compression ratio >= threshold) t.Run("no penalty case", func(t *testing.T) { - data := make([]byte, 100) // txSize = 100 + data := make([]byte, 100) // txSize = 100 + compressionRatio := new(big.Int).SetInt64(6_000_000_000) // exactly at threshold - // Since compression ratio will be >= penaltyThreshold, penalty = 1 * PRECISION + // Since compression ratio >= penaltyThreshold, penalty = 1 * PRECISION // feePerByte = execScalar * l1BaseFee + blobScalar * l1BlobBaseFee = 10 * 1_000_000_000 + 20 * 1_000_000_000 = 30_000_000_000 // l1DataFee = feePerByte * txSize * penalty / PRECISION / PRECISION // = 30_000_000_000 * 100 * 1_000_000_000 / 1_000_000_000 / 1_000_000_000 = 3000 @@ -59,6 +62,7 @@ func TestL1DataFeeFeynman(t *testing.T) { blobScalar, penaltyThreshold, penaltyFactor, + compressionRatio, ) assert.Equal(t, expected, actual) @@ -66,11 +70,10 @@ func TestL1DataFeeFeynman(t *testing.T) { // Test case 2: With penalty (compression ratio < threshold) t.Run("with penalty case", func(t *testing.T) { - data := make([]byte, 100) // txSize = 100 - - // Set a high penalty threshold to force penalty application - highPenaltyThreshold := new(big.Int).SetInt64(1000_000_000_000) // 1000 * PRECISION + data := make([]byte, 100) // txSize = 100 + compressionRatio := new(big.Int).SetInt64(5_000_000_000) // below threshold + // Since compression ratio < penaltyThreshold, penalty = penaltyFactor // feePerByte = execScalar * l1BaseFee + blobScalar * l1BlobBaseFee = 30_000_000_000 // l1DataFee = feePerByte * txSize * penaltyFactor / PRECISION / PRECISION // = 30_000_000_000 * 100 * 2_000_000_000 / 1_000_000_000 / 1_000_000_000 = 6000 @@ -83,10 +86,54 @@ func TestL1DataFeeFeynman(t *testing.T) { l1BlobBaseFee, execScalar, blobScalar, - highPenaltyThreshold, + penaltyThreshold, penaltyFactor, + compressionRatio, ) assert.Equal(t, expected, actual) }) } + +func TestEstimateTxCompressionRatio(t *testing.T) { + // Mock config that would select a specific codec version + // Note: You'll need to adjust this based on your actual params.ChainConfig structure + + t.Run("empty data", func(t *testing.T) { + data := []byte{} + // Should return 1.0 ratio (PRECISION) + ratio := estimateTxCompressionRatio(data, 1000000, 1700000000, params.TestChainConfig) + assert.NotNil(t, ratio) + // The exact value depends on rcfg.Precision, but should be the "1.0" equivalent + }) + + t.Run("non-empty data", func(t *testing.T) { + // Create some compressible data + data := make([]byte, 1000) + for i := range data { + data[i] = byte(i % 10) // Create patterns for better compression + } + + ratio := estimateTxCompressionRatio(data, 1000000, 1700000000, params.TestChainConfig) + assert.NotNil(t, ratio) + // Should return a ratio > 1.0 (since compressed size < original size) + }) +} + +func TestCalculatePenalty(t *testing.T) { + precision := new(big.Int).SetInt64(1_000_000_000) // PRECISION + penaltyThreshold := new(big.Int).SetInt64(6_000_000_000) // 6 * PRECISION + penaltyFactor := new(big.Int).SetInt64(2_000_000_000) // 2 * PRECISION + + t.Run("no penalty when ratio >= threshold", func(t *testing.T) { + compressionRatio := new(big.Int).SetInt64(6_000_000_000) // exactly at threshold + penalty := calculatePenalty(compressionRatio, penaltyThreshold, penaltyFactor) + assert.Equal(t, precision, penalty) + }) + + t.Run("penalty when ratio < threshold", func(t *testing.T) { + compressionRatio := new(big.Int).SetInt64(5_000_000_000) // below threshold + penalty := calculatePenalty(compressionRatio, penaltyThreshold, penaltyFactor) + assert.Equal(t, penaltyFactor, penalty) + }) +} From dd262c10040ad3fad2adfeb934323d7bd66d3b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 25 Jun 2025 13:39:27 +0200 Subject: [PATCH 20/23] remove incorrect merge artifact --- miner/scroll_worker.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/miner/scroll_worker.go b/miner/scroll_worker.go index e96167ef34d4..56b458e4d5a7 100644 --- a/miner/scroll_worker.go +++ b/miner/scroll_worker.go @@ -638,11 +638,6 @@ func (w *worker) handleForks(parent *types.Block) (bool, error) { misc.ApplyFeynmanHardFork(w.current.state) } - // Apply Feynman hard fork - if w.chainConfig.IsFeynmanTransitionBlock(w.current.header.Time, parent.Time()) { - misc.ApplyFeynmanHardFork(w.current.state) - } - // Apply EIP-2935 if w.chainConfig.IsFeynman(w.current.header.Time) { context := core.NewEVMBlockContext(w.current.header, w.chain, w.chainConfig, nil) From bd7f65867cca6519f5d1ac2d300882d2cd26d869 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Wed, 25 Jun 2025 20:38:58 +0800 Subject: [PATCH 21/23] error handling --- rollup/fees/rollup_fee.go | 18 +++++++++++------- rollup/fees/rollup_fee_test.go | 8 +++++--- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index 51bdd24af6da..e6540bad19d0 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -2,6 +2,7 @@ package fees import ( "bytes" + "fmt" "math" "math/big" @@ -169,21 +170,21 @@ func readGPOStorageSlots(addr common.Address, state StateDB) gpoState { // estimateTxCompressionRatio estimates the compression ratio for transaction data using da-codec // compression_ratio(tx) = size(tx) * PRECISION / size(zstd(tx)) -func estimateTxCompressionRatio(data []byte, blockNumber uint64, blockTime uint64, config *params.ChainConfig) *big.Int { +func estimateTxCompressionRatio(data []byte, blockNumber uint64, blockTime uint64, config *params.ChainConfig) (*big.Int, error) { if len(data) == 0 { - return rcfg.Precision + return nil, fmt.Errorf("raw data is empty") } // Compress data using da-codec compressed, err := encoding.CompressScrollBatchBytes(data, blockNumber, blockTime, config) if err != nil { log.Error("Batch compression failed, using 1.0 compression ratio", "error", err, "data size", len(data), "data", common.Bytes2Hex(data)) - return rcfg.Precision + return nil, fmt.Errorf("batch compression failed: %w", err) } if len(compressed) == 0 { log.Error("Compressed data is empty, using 1.0 compression ratio", "data size", len(data), "data", common.Bytes2Hex(data)) - return rcfg.Precision + return nil, fmt.Errorf("compressed data is empty") } // compression_ratio = size(tx) * PRECISION / size(zstd(tx)) @@ -194,13 +195,13 @@ func estimateTxCompressionRatio(data []byte, blockNumber uint64, blockTime uint6 // This behavior is consistent with DA Batch compression in codecv7 and later versions if len(compressed) >= len(data) { log.Debug("Compressed data is bigger or equal to the original data, using 1.0 compression ratio", "original size", len(data), "compressed size", len(compressed)) - return rcfg.Precision + return rcfg.Precision, nil } ratio := new(big.Int).Mul(originalSize, rcfg.Precision) ratio.Div(ratio, compressedSize) - return ratio + return ratio, nil } // calculatePenalty computes the penalty multiplier based on compression ratio @@ -336,7 +337,10 @@ func CalculateL1DataFee(tx *types.Transaction, state StateDB, config *params.Cha l1DataFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) } else { // Calculate compression ratio for Feynman - compressionRatio := estimateTxCompressionRatio(raw, blockNumber.Uint64(), blockTime, config) + compressionRatio, err := estimateTxCompressionRatio(raw, blockNumber.Uint64(), blockTime, config) + if err != nil { + return nil, fmt.Errorf("failed to estimate compression ratio: tx hash=%s: %w", tx.Hash().Hex(), err) + } // The contract slot for commitScalar is changed to execScalar in Feynman l1DataFee = calculateEncodedL1DataFeeFeynman( diff --git a/rollup/fees/rollup_fee_test.go b/rollup/fees/rollup_fee_test.go index 5dd96e3cf053..a4197321cfbd 100644 --- a/rollup/fees/rollup_fee_test.go +++ b/rollup/fees/rollup_fee_test.go @@ -102,8 +102,9 @@ func TestEstimateTxCompressionRatio(t *testing.T) { t.Run("empty data", func(t *testing.T) { data := []byte{} // Should return 1.0 ratio (PRECISION) - ratio := estimateTxCompressionRatio(data, 1000000, 1700000000, params.TestChainConfig) - assert.NotNil(t, ratio) + ratio, err := estimateTxCompressionRatio(data, 1000000, 1700000000, params.TestChainConfig) + assert.Error(t, err, "raw data is empty") + assert.Nil(t, ratio) // The exact value depends on rcfg.Precision, but should be the "1.0" equivalent }) @@ -114,7 +115,8 @@ func TestEstimateTxCompressionRatio(t *testing.T) { data[i] = byte(i % 10) // Create patterns for better compression } - ratio := estimateTxCompressionRatio(data, 1000000, 1700000000, params.TestChainConfig) + ratio, err := estimateTxCompressionRatio(data, 1000000, 1700000000, params.TestChainConfig) + assert.NoError(t, err) assert.NotNil(t, ratio) // Should return a ratio > 1.0 (since compressed size < original size) }) From ee255a4e1d38687d13b238795919d827dbebe968 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Thu, 26 Jun 2025 01:06:23 +0800 Subject: [PATCH 22/23] update da-codec commit --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e62aaf5349d1..381dfa3d8ff1 100644 --- a/go.mod +++ b/go.mod @@ -51,7 +51,7 @@ require ( github.com/prometheus/tsdb v0.7.1 github.com/rjeczalik/notify v0.9.1 github.com/rs/cors v1.7.0 - github.com/scroll-tech/da-codec v0.1.3-0.20250625104355-9592886c0145 + github.com/scroll-tech/da-codec v0.1.3-0.20250625161338-efd0b3af40e3 github.com/scroll-tech/zktrie v0.8.4 github.com/shirou/gopsutil v3.21.11+incompatible github.com/sourcegraph/conc v0.3.0 diff --git a/go.sum b/go.sum index f36a3a0781ca..b9992915c3b5 100644 --- a/go.sum +++ b/go.sum @@ -396,8 +396,8 @@ github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncj github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/scroll-tech/da-codec v0.1.3-0.20250625104355-9592886c0145 h1:dQQf/V7lYPWALJHAC7wdWtLrbX8j2E+cxzZyoPNeGDQ= -github.com/scroll-tech/da-codec v0.1.3-0.20250625104355-9592886c0145/go.mod h1:T+370kLxwACnmWaq4rgtKGyLCd7QSE6iy0JLfCp1qj4= +github.com/scroll-tech/da-codec v0.1.3-0.20250625161338-efd0b3af40e3 h1:Yh49UAsnz3r7z8F9+7ZExwwSm43ocnVzvbArgDMMMDw= +github.com/scroll-tech/da-codec v0.1.3-0.20250625161338-efd0b3af40e3/go.mod h1:Z6kN5u2khPhiqHyk172kGB7o38bH/nj7Ilrb/46wZGg= github.com/scroll-tech/zktrie v0.8.4 h1:UagmnZ4Z3ITCk+aUq9NQZJNAwnWl4gSxsLb2Nl7IgRE= github.com/scroll-tech/zktrie v0.8.4/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk= github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= From bad7cac34ba3a7d2c4f1c6ff772865b5b5589956 Mon Sep 17 00:00:00 2001 From: colinlyguo Date: Thu, 26 Jun 2025 17:25:51 +0800 Subject: [PATCH 23/23] update da-codec commit --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 381dfa3d8ff1..9c432ada8f08 100644 --- a/go.mod +++ b/go.mod @@ -51,7 +51,7 @@ require ( github.com/prometheus/tsdb v0.7.1 github.com/rjeczalik/notify v0.9.1 github.com/rs/cors v1.7.0 - github.com/scroll-tech/da-codec v0.1.3-0.20250625161338-efd0b3af40e3 + github.com/scroll-tech/da-codec v0.1.3-0.20250626091118-58b899494da6 github.com/scroll-tech/zktrie v0.8.4 github.com/shirou/gopsutil v3.21.11+incompatible github.com/sourcegraph/conc v0.3.0 diff --git a/go.sum b/go.sum index b9992915c3b5..1bfb050837ab 100644 --- a/go.sum +++ b/go.sum @@ -396,8 +396,8 @@ github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncj github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/scroll-tech/da-codec v0.1.3-0.20250625161338-efd0b3af40e3 h1:Yh49UAsnz3r7z8F9+7ZExwwSm43ocnVzvbArgDMMMDw= -github.com/scroll-tech/da-codec v0.1.3-0.20250625161338-efd0b3af40e3/go.mod h1:Z6kN5u2khPhiqHyk172kGB7o38bH/nj7Ilrb/46wZGg= +github.com/scroll-tech/da-codec v0.1.3-0.20250626091118-58b899494da6 h1:vb2XLvQwCf+F/ifP6P/lfeiQrHY6+Yb/E3R4KHXLqSE= +github.com/scroll-tech/da-codec v0.1.3-0.20250626091118-58b899494da6/go.mod h1:Z6kN5u2khPhiqHyk172kGB7o38bH/nj7Ilrb/46wZGg= github.com/scroll-tech/zktrie v0.8.4 h1:UagmnZ4Z3ITCk+aUq9NQZJNAwnWl4gSxsLb2Nl7IgRE= github.com/scroll-tech/zktrie v0.8.4/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk= github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=