Skip to content

feat(feynman): compute compression ratio on tx data #1217

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion params/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 = 62 // Patch version component of the current release
VersionPatch = 63 // Patch version component of the current release
VersionMeta = "mainnet" // Version metadata to append to the version string
)

Expand Down
23 changes: 15 additions & 8 deletions rollup/fees/rollup_fee.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ import (
"github.com/scroll-tech/go-ethereum/rollup/rcfg"
)

var U256MAX *big.Int

func init() {
U256MAX, _ = new(big.Int).SetString("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)
}

var (
// txExtraDataBytes is the number of bytes that we commit to L1 in addition
// to the RLP-encoded signed transaction. Note that these are all assumed
Expand Down Expand Up @@ -168,11 +174,12 @@ func readGPOStorageSlots(addr common.Address, state StateDB) gpoState {
return gpoState
}

// estimateTxCompressionRatio estimates the compression ratio for transaction data using da-codec
// estimateTxCompressionRatio estimates the compression ratio for `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, error) {
// By definition, the compression ratio of empty data is infinity
if len(data) == 0 {
return nil, fmt.Errorf("raw data is empty")
return U256MAX, nil
}

// Compress data using da-codec
Expand All @@ -187,17 +194,16 @@ func estimateTxCompressionRatio(data []byte, blockNumber uint64, blockTime uint6
return nil, fmt.Errorf("compressed data is empty")
}

// 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, nil
}

// compression_ratio = size(tx) * PRECISION / size(zstd(tx))
originalSize := new(big.Int).SetUint64(uint64(len(data)))
compressedSize := new(big.Int).SetUint64(uint64(len(compressed)))

ratio := new(big.Int).Mul(originalSize, rcfg.Precision)
ratio.Div(ratio, compressedSize)

Expand Down Expand Up @@ -337,7 +343,8 @@ 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, err := estimateTxCompressionRatio(raw, blockNumber.Uint64(), blockTime, config)
// Note: We compute the transaction ratio on tx.data, not on the full encoded transaction.
compressionRatio, err := estimateTxCompressionRatio(tx.Data(), blockNumber.Uint64(), blockTime, config)
if err != nil {
return nil, fmt.Errorf("failed to estimate compression ratio: tx hash=%s: %w", tx.Hash().Hex(), err)
}
Expand Down
61 changes: 36 additions & 25 deletions rollup/fees/rollup_fee_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,16 @@ 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

calcCompressionRatio := func(data []byte) (*big.Int, error) {
return estimateTxCompressionRatio(data, 1000000, 1700000000, params.TestChainConfig)
}

t.Run("empty data", func(t *testing.T) {
data := []byte{}
// Should return 1.0 ratio (PRECISION)
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
ratio, err := calcCompressionRatio(data)
assert.NoError(t, err)
assert.NotNil(t, ratio)
assert.Equal(t, U256MAX, ratio) // empty data has max compression ratio by definition
})

t.Run("non-empty data", func(t *testing.T) {
Expand All @@ -116,64 +119,72 @@ func TestEstimateTxCompressionRatio(t *testing.T) {
data[i] = byte(i % 10) // Create patterns for better compression
}

ratio, err := estimateTxCompressionRatio(data, 1000000, 1700000000, params.TestChainConfig)
ratio, err := calcCompressionRatio(data)
assert.NoError(t, err)
assert.NotNil(t, ratio)
// Should return a ratio > 1.0 (since compressed size < original size)
})

t.Run("eth-transfer", func(t *testing.T) {
// https://scrollscan.com/tx/0x8c7eba9a56e25c4402a1d9fdbe6fbe70e6f6f89484b2e4f5c329258a924193b4
data := common.Hex2Bytes("02f86b83082750830461a40183830fb782523f94802b65b5d9016621e66003aed0b16615093f328b8080c001a0a1fa6bbede5ae355eaec83fdcda65eab240476895e649576552850de726596cca0424eb1f5221865817b270d85caf8611d35ea6d7c2e86c9c31af5c06df04a2587")
ratio, err := estimateTxCompressionRatio(data, 1000000, 1700000000, params.TestChainConfig)
data := common.Hex2Bytes("") // empty payload
ratio, err := calcCompressionRatio(data)
assert.NoError(t, err)
assert.NotNil(t, ratio)
assert.Equal(t, big.NewInt(1_000_000_000), ratio) // 1x (not compressible)
assert.Equal(t, U256MAX, ratio) // empty data is infinitely compressible by definition
})

t.Run("scr-transfer", func(t *testing.T) {
// https://scrollscan.com/tx/0x7b681ce914c9774aff364d2b099b2ba41dea44bcd59dbebb9d4c4b6853893179
data := common.Hex2Bytes("02f8b28308275001830f4240840279876683015c2894d29687c813d741e2f938f4ac377128810e217b1b80b844a9059cbb000000000000000000000000687b50a70d33d71f9a82dd330b8c091e4d77250800000000000000000000000000000000000000000000000ac96dda943e512bb9c080a0fdacacd07ed7c708e2193b803d731d3d288dcd39c317f321f243cd790406868ba0285444ab799632c88fd47c874c218bceb1589843949b5bc0f3ead1df069f3233")
ratio, err := estimateTxCompressionRatio(data, 1000000, 1700000000, params.TestChainConfig)
data := common.Hex2Bytes("a9059cbb000000000000000000000000687b50a70d33d71f9a82dd330b8c091e4d77250800000000000000000000000000000000000000000000000ac96dda943e512bb9")
ratio, err := calcCompressionRatio(data)
assert.NoError(t, err)
assert.NotNil(t, ratio)
assert.Equal(t, big.NewInt(1_117_283_950), ratio) // 1.1x
assert.Equal(t, big.NewInt(1_387_755_102), ratio) // 1.4x
})

t.Run("syncswap-swap", func(t *testing.T) {
// https://scrollscan.com/tx/0x59a7b72503400b6719f3cb670c7b1e7e45ce5076f30b98bdaad3b07a5d0fbc02
data := common.Hex2Bytes("f902cf830887d783a57282830493e09480e38291e06339d10aab483c65695d004dbd5c6980b902642cc4081e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000005ec79b80000000000000000000000000000000000000000000000000003328b944c400000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000053000000000000000000000000000000000000040000000000000000000000000000000000000000000000000091a94863ca800000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000814a23b053fd0f102aeeda0459215c2444799c7000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000600000000000000000000000005300000000000000000000000000000000000004000000000000000000000000485ca81b70255da2fe3fd0814b57d1b08fce784e0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000083104ec3a050db0fbfa3fd83aa9077abdd4edb3dc504661d6fb3b39f973fe994de8fb0ac41a044983fa3d16aa0e156a1b3382fa763f9831be5a5c158f849be524d41d100ab52")
ratio, err := estimateTxCompressionRatio(data, 1000000, 1700000000, params.TestChainConfig)
data := common.Hex2Bytes("2cc4081e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000005ec79b80000000000000000000000000000000000000000000000000003328b944c400000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000053000000000000000000000000000000000000040000000000000000000000000000000000000000000000000091a94863ca800000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000814a23b053fd0f102aeeda0459215c2444799c7000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000600000000000000000000000005300000000000000000000000000000000000004000000000000000000000000485ca81b70255da2fe3fd0814b57d1b08fce784e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000")
ratio, err := calcCompressionRatio(data)
assert.NoError(t, err)
assert.NotNil(t, ratio)
assert.Equal(t, big.NewInt(3_059_322_033), ratio) // 3.1x
assert.Equal(t, big.NewInt(4_857_142_857), ratio) // 4.8x
})

t.Run("uniswap-swap", func(t *testing.T) {
// https://scrollscan.com/tx/0x65b268bd8ef416f44983ee277d748de044243272b0f106b71ff03cc8501a05da
data := common.Hex2Bytes("f9014e830887e0836b92a7830493e094fc30937f5cde93df8d48acaf7e6f5d8d8a31f63680b8e45023b4df00000000000000000000000006efdbff2a14a7c8e15944d1f4a48f9f95f663a4000000000000000000000000530000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000485ca81b70255da2fe3fd0814b57d1b08fce784e000000000000000000000000000000000000000000000000006a94d74f43000000000000000000000000000000000000000000000000000000000000045af675000000000000000000000000000000000000000000000000000000000000000083104ec4a0a527358d5bfb89dcc7939265c6add9faf4697415174723e509f795ad44021d98a0776f4a8a8a51da98b70d960a5bd1faf3c79b8dddc0bc2c642a4c2634c6990f02")
ratio, err := estimateTxCompressionRatio(data, 1000000, 1700000000, params.TestChainConfig)
data := common.Hex2Bytes("5023b4df00000000000000000000000006efdbff2a14a7c8e15944d1f4a48f9f95f663a4000000000000000000000000530000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000485ca81b70255da2fe3fd0814b57d1b08fce784e000000000000000000000000000000000000000000000000006a94d74f43000000000000000000000000000000000000000000000000000000000000045af6750000000000000000000000000000000000000000000000000000000000000000")
ratio, err := calcCompressionRatio(data)
assert.NoError(t, err)
assert.NotNil(t, ratio)
assert.Equal(t, big.NewInt(1_710_659_898), ratio) // 1.7x
assert.Equal(t, big.NewInt(2_620_689_655), ratio) // 2.6x
})

t.Run("etherfi-deposit", func(t *testing.T) {
// https://scrollscan.com/tx/0x41a77736afd54134b6c673e967c9801e326495074012b4033bd557920cbe5a71
data := common.Hex2Bytes("02f901d58308275082f88a834c4b4084044c7166831066099462f623161fdb6564925c3f9b783cbdfef4ce8aec80b9016463baa26000000000000000000000000077a7e3215a621a9935d32a046212ebfcffa3bff900000000000000000000000006efdbff2a14a7c8e15944d1f4a48f9f95f663a400000000000000000000000008c6f91e2b681faf5e17227f2a44c307b3c1364c0000000000000000000000000000000000000000000000000000000002d4cae000000000000000000000000000000000000000000000000000000000028f7f83000000000000000000000000249e3fa81d73244f956ecd529715323b6d02f24b00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000041a95314c3a11f86cc673f2afd60d27f559cb2edcc0da5af030adffc97f9a5edc3314efbadd32878e289017f644a4afa365da5367fefe583f7c4ff0c6047e2c1ff1b00000000000000000000000000000000000000000000000000000000000000c080a05b2d22b8aaf6d334471e74899cfc4c81186f8a94f278c97ee211727d8027ceafa0450352d9a1782180c27a03889d317d31e725dda38a5bd3c0531950b879ed50a1")
ratio, err := estimateTxCompressionRatio(data, 1000000, 1700000000, params.TestChainConfig)
data := common.Hex2Bytes("63baa26000000000000000000000000077a7e3215a621a9935d32a046212ebfcffa3bff900000000000000000000000006efdbff2a14a7c8e15944d1f4a48f9f95f663a400000000000000000000000008c6f91e2b681faf5e17227f2a44c307b3c1364c0000000000000000000000000000000000000000000000000000000002d4cae000000000000000000000000000000000000000000000000000000000028f7f83000000000000000000000000249e3fa81d73244f956ecd529715323b6d02f24b00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000041a95314c3a11f86cc673f2afd60d27f559cb2edcc0da5af030adffc97f9a5edc3314efbadd32878e289017f644a4afa365da5367fefe583f7c4ff0c6047e2c1ff1b00000000000000000000000000000000000000000000000000000000000000")
ratio, err := calcCompressionRatio(data)
assert.NoError(t, err)
assert.NotNil(t, ratio)
assert.Equal(t, big.NewInt(1_496_835_443), ratio) // 1.4x
assert.Equal(t, big.NewInt(1_788_944_723), ratio) // 1.8x
})

t.Run("edgepushoracle-postupdate", func(t *testing.T) {
// https://scrollscan.com/tx/0x8271c68146a3b07b1ebf52ce0b550751f49cbd72fa0596ef14ff56d1f23a0bec
data := common.Hex2Bytes("f9046f83015e4c836e0b6b8303cbf8946a5b3ab3274b738eab25205af6e2d4dd7781292480b9040449a1a4fb000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000005f725f60000000000000000000000000000000000000000000000000000000003d0cac600000000000000000000000000000000000000000000000000000000685d50cd000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000004155903b95865fc5a5dd7d4d876456140dd0b815695647fc41eb1924f4cfe267265130b5a5d77125c44cf6a5a81edba6d5850ba00f90ab83281c9b44e17528fd74010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000416f000e0498733998e6a1a6454e116c1b1f95f7e000400b6a54029406cf288bdc615b62de8e2db533d6010ca57001e0b8a4b3f05ed516a31830516c52b9df206e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410dabc77a807d729ff62c3be740d492d884f026ad2770fa7c4bdec569e201643656b07f2009d2129173738571417734a3df051cebc7b8233bec6d9471c21c098700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041eb009614c939170e9ff3d3e06c3a2c45810fe46a364ce28ecec5e220f5fd86cd6e0f70ab9093dd6b22b69980246496b600c8fcb054047962d4128efa48b692f301000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041a31b4dd4f0a482372d75c7a8c5f11aa8084a5f358579866f1d25a26a15beb2b5153400bfa7fa3d6fba138c02dd1eb8a5a97d62178d98c5632a153396a566e5ed000000000000000000000000000000000000000000000000000000000000000083104ec4a05cb4eee77676d432c672008594825b957d34ae5dd786ed294501849bb1ce285aa01325f37cdc945863ec0474932102bc944cb98a663db6d30ae23c2ebb5f9ce070")
ratio, err := estimateTxCompressionRatio(data, 1000000, 1700000000, params.TestChainConfig)
data := common.Hex2Bytes("49a1a4fb000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000005f725f60000000000000000000000000000000000000000000000000000000003d0cac600000000000000000000000000000000000000000000000000000000685d50cd000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000004155903b95865fc5a5dd7d4d876456140dd0b815695647fc41eb1924f4cfe267265130b5a5d77125c44cf6a5a81edba6d5850ba00f90ab83281c9b44e17528fd74010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000416f000e0498733998e6a1a6454e116c1b1f95f7e000400b6a54029406cf288bdc615b62de8e2db533d6010ca57001e0b8a4b3f05ed516a31830516c52b9df206e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410dabc77a807d729ff62c3be740d492d884f026ad2770fa7c4bdec569e201643656b07f2009d2129173738571417734a3df051cebc7b8233bec6d9471c21c098700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041eb009614c939170e9ff3d3e06c3a2c45810fe46a364ce28ecec5e220f5fd86cd6e0f70ab9093dd6b22b69980246496b600c8fcb054047962d4128efa48b692f301000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041a31b4dd4f0a482372d75c7a8c5f11aa8084a5f358579866f1d25a26a15beb2b5153400bfa7fa3d6fba138c02dd1eb8a5a97d62178d98c5632a153396a566e5ed0000000000000000000000000000000000000000000000000000000000000000")
ratio, err := calcCompressionRatio(data)
assert.NoError(t, err)
assert.NotNil(t, ratio)
assert.Equal(t, big.NewInt(2_441_805_225), ratio) // 2.4x
})

t.Run("intmax-post", func(t *testing.T) {
// https://scrollscan.com/tx/0x7244e27223cdd79ba0f0e3990c746e5d524e35dbcc200f0a7e664ffdc6d08eef
data := common.Hex2Bytes("9b6babf0f0372bb253e060ecbdd3dbef8b832b0e743148bd807bfcf665593a56a18bac69000000000000000000000000000000000000000000000000000000006861676d0000000000000000000000000000000000000000000000000000000000000015800000000000000000000000000000000000000000000000000000000000000029a690c4ef1e18884a11f73c8595fb721f964a3e2bee809800c474278f024bcd05a76119827e6c464cee8620f616a9a23d41305eb9f9682f9d2eaf964325fcd71147783453566f27ce103a2398d96719ee22ba51b89b92cdf952af817929329403b75ae310b23cf250041d53c82bef431fa2527e2dd68b49f45f06feb2bd09f011358fe2650b8987ea2bb39bb6e28ce770f4fc9c4f064d0ae7573a1450452b501a5b0d3454d254dbf9db7094f4ca1f5056143f5c70dee4126443a6150d9e51bd05dac7e9a2bd48a8797ac6e9379d400c5ce1815b10846eaf0d80dca3a727ffd0075387e0f1bc1b363c81ecf8d05a4b654ac6fbe1cdc7c741a5c0bbeabde4138906009129ca033af12094fd7306562d9735b2fe757f021b7eb3320f8a814a286a10130969de2783e49871b80e967cfba630e6bdef2fd1d2b1076c6c3f5fd9ae5800000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000012a98f1556efe81340fad3e59044b8139ce62f1d5d50b44b680de9422b1ddbf1a")
ratio, err := calcCompressionRatio(data)
assert.NoError(t, err)
assert.NotNil(t, ratio)
assert.Equal(t, big.NewInt(2_139_097_744), ratio) // 2.1x
assert.Equal(t, big.NewInt(1_298_578_199), ratio) // 1.3x
})
}

Expand Down
Loading