From a0a48928712774f8264d2df11f70ba99d82719a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 5 Nov 2025 10:55:16 +0100 Subject: [PATCH 1/5] feat: add compute_compressed_size for Galileo --- Cargo.lock | 2 +- crates/rpc/rpc-convert/src/transaction.rs | 1 + crates/scroll/alloy/evm/src/block/mod.rs | 22 +-- crates/scroll/alloy/evm/src/lib.rs | 6 +- crates/scroll/alloy/evm/src/tx/compression.rs | 145 +++++++++++++----- crates/scroll/alloy/evm/src/tx/mod.rs | 38 +++-- crates/scroll/evm/src/execute.rs | 22 +-- crates/scroll/evm/src/l1.rs | 4 +- crates/scroll/evm/src/lib.rs | 4 +- crates/scroll/txpool/src/validator.rs | 7 +- 10 files changed, 168 insertions(+), 83 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db6813ed037..b49d5d44b25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11471,7 +11471,7 @@ dependencies = [ [[package]] name = "revm-scroll" version = "0.1.0" -source = "git+https://github.com/scroll-tech/scroll-revm#d6b77e226ce20646d0ddf3dfe3b1fb3ec8a58cc3" +source = "git+https://github.com/scroll-tech/scroll-revm#c87b934962b84bcb6fda0fe49bd248d87ff6766e" dependencies = [ "auto_impl", "enumn", diff --git a/crates/rpc/rpc-convert/src/transaction.rs b/crates/rpc/rpc-convert/src/transaction.rs index b463dbc1229..5b0a4b1af51 100644 --- a/crates/rpc/rpc-convert/src/transaction.rs +++ b/crates/rpc/rpc-convert/src/transaction.rs @@ -1066,6 +1066,7 @@ pub mod scroll { self.as_ref().clone().try_into_tx_env(cfg_env, block_env)?, Some(Bytes::new()), Some(TX_L1_FEE_PRECISION_U256), + Some(0), )) } } diff --git a/crates/scroll/alloy/evm/src/block/mod.rs b/crates/scroll/alloy/evm/src/block/mod.rs index 22880f681b6..a94cb311803 100644 --- a/crates/scroll/alloy/evm/src/block/mod.rs +++ b/crates/scroll/alloy/evm/src/block/mod.rs @@ -10,8 +10,8 @@ use crate::{ feynman::apply_feynman_hard_fork, }, system_caller::ScrollSystemCaller, - FromTxWithCompressionRatio, ScrollDefaultPrecompilesFactory, ScrollEvm, ScrollEvmFactory, - ScrollPrecompilesFactory, ScrollTransactionIntoTxEnv, ToTxWithCompressionRatio, + FromTxWithCompressionInfo, ScrollDefaultPrecompilesFactory, ScrollEvm, ScrollEvmFactory, + ScrollPrecompilesFactory, ScrollTransactionIntoTxEnv, ToTxWithCompressionInfo, }; use alloc::{boxed::Box, format, vec::Vec}; @@ -39,8 +39,8 @@ use revm_scroll::builder::ScrollContext; use scroll_alloy_consensus::L1_MESSAGE_TRANSACTION_TYPE; use scroll_alloy_hardforks::{ScrollHardfork, ScrollHardforks}; -/// A cache for transaction compression ratios. -pub type ScrollTxCompressionRatios = Vec; +/// A cache for transaction compression infos, i.e. (compression ratio, compressed size) pairs. +pub type ScrollTxCompressionInfos = Vec<(U256, usize)>; /// Context for Scroll Block Execution. #[derive(Debug, Default, Clone)] @@ -102,30 +102,30 @@ where DB = &'db mut State, Tx: FromRecoveredTx + FromTxWithEncoded - + FromTxWithCompressionRatio, + + FromTxWithCompressionInfo, >, R: ScrollReceiptBuilder, Spec: ScrollHardforks, { /// Executes all transactions in a block, applying pre and post execution changes. The provided - /// transaction compression ratios are expected to be in the same order as the + /// transaction compression infos are expected to be in the same order as the /// transactions. pub fn execute_block_with_compression_cache( mut self, transactions: impl IntoIterator< Item = impl ExecutableTx - + ToTxWithCompressionRatio<::Transaction>, + + ToTxWithCompressionInfo<::Transaction>, >, - compression_ratios: impl IntoIterator, + compression_infos: impl IntoIterator, ) -> Result, BlockExecutionError> where Self: Sized, { self.apply_pre_execution_changes()?; - for (tx, compression_ratio) in transactions.into_iter().zip(compression_ratios.into_iter()) + for (tx, (compression_ratio, compressed_size)) in transactions.into_iter().zip(compression_infos.into_iter()) { - let tx = tx.with_compression_ratio(compression_ratio); + let tx = tx.with_compression_info(compression_ratio, compressed_size); self.execute_transaction(&tx)?; } @@ -335,10 +335,12 @@ where let l1_block_info = &self.ctx().chain; let transaction_rlp_bytes = self.ctx().tx.rlp_bytes.as_ref()?; let compression_ratio = self.ctx().tx.compression_ratio; + let compressed_size = self.ctx().tx.compressed_size; Some(l1_block_info.calculate_tx_l1_cost( transaction_rlp_bytes, self.ctx().cfg.spec, compression_ratio, + compressed_size, )) } } diff --git a/crates/scroll/alloy/evm/src/lib.rs b/crates/scroll/alloy/evm/src/lib.rs index bc0ca96c2c5..48fba905870 100644 --- a/crates/scroll/alloy/evm/src/lib.rs +++ b/crates/scroll/alloy/evm/src/lib.rs @@ -7,13 +7,13 @@ mod block; pub use block::{ curie, feynman, EvmExt, ReceiptBuilderCtx, ScrollBlockExecutionCtx, ScrollBlockExecutor, - ScrollBlockExecutorFactory, ScrollReceiptBuilder, ScrollTxCompressionRatios, + ScrollBlockExecutorFactory, ScrollReceiptBuilder, ScrollTxCompressionInfos, }; mod tx; pub use tx::{ - compute_compression_ratio, FromTxWithCompressionRatio, ScrollTransactionIntoTxEnv, - ToTxWithCompressionRatio, WithCompressionRatio, + compute_compression_ratio, compute_compressed_size, FromTxWithCompressionInfo, ScrollTransactionIntoTxEnv, + ToTxWithCompressionInfo, WithCompressionInfo, }; mod system_caller; diff --git a/crates/scroll/alloy/evm/src/tx/compression.rs b/crates/scroll/alloy/evm/src/tx/compression.rs index da406b2bdff..cf0eefb5b53 100644 --- a/crates/scroll/alloy/evm/src/tx/compression.rs +++ b/crates/scroll/alloy/evm/src/tx/compression.rs @@ -6,7 +6,7 @@ use alloy_evm::{RecoveredTx, ToTxEnv}; use alloy_primitives::{Address, Bytes, TxKind, U256}; use revm::context::TxEnv; use scroll_alloy_consensus::{ScrollTxEnvelope, TxL1Message}; -pub use zstd_compression::compute_compression_ratio; +pub use zstd_compression::{compute_compression_ratio, compute_compressed_size}; #[cfg(feature = "zstd_compression")] mod zstd_compression { @@ -16,14 +16,14 @@ mod zstd_compression { use encoder_standard::{init_zstd_encoder, N_BLOCK_SIZE_TARGET}; use revm_scroll::l1block::TX_L1_FEE_PRECISION_U256; - /// Computes the compression ratio for the provided bytes. + /// Computes the compressed size for the provided bytes. /// /// This is computed as: - /// `max(1, original_size * TX_L1_FEE_PRECISION_U256 / encoded_size)` - pub fn compute_compression_ratio>(bytes: &T) -> U256 { - // By definition, the compression ratio of empty data is infinity + /// `min(encoded_size, original_size)` + pub fn compute_compressed_size>(bytes: &T) -> usize { + // Compressed size of empty data is 0. if bytes.as_ref().is_empty() { - return U256::MAX + return 0; } // Instantiate the compressor @@ -41,8 +41,23 @@ mod zstd_compression { let result = compressor.finish().expect("failed to finish compression"); let encoded_bytes_len = result.len(); - // Make sure that the compression ratio >= 1.0 - if encoded_bytes_len > original_bytes_len { + if encoded_bytes_len > original_bytes_len { original_bytes_len } else { encoded_bytes_len } + } + + /// Computes the compression ratio for the provided bytes. + /// + /// This is computed as: + /// `max(1, original_size * TX_L1_FEE_PRECISION_U256 / encoded_size)` + pub fn compute_compression_ratio>(bytes: &T) -> U256 { + // By definition, the compression ratio of empty data is infinity + if bytes.as_ref().is_empty() { + return U256::MAX + } + + let original_bytes_len = bytes.as_ref().len(); + let encoded_bytes_len = compute_compressed_size(bytes); + + if encoded_bytes_len == original_bytes_len { return TX_L1_FEE_PRECISION_U256; } @@ -57,6 +72,13 @@ mod zstd_compression { mod zstd_compression { use super::*; + /// Computes the compressed size for the provided bytes. This panics if the compression + /// feature is not enabled. This is to support `no_std` environments where zstd is not + /// available. + pub fn compute_compressed_size>(bytes: &T) -> usize { + panic!("Compression feature is not enabled. Please enable the 'compression' feature to use this function."); + } + /// Computes the compression ratio for the provided bytes. This panics if the compression /// feature is not enabled. This is to support `no_std` environments where zstd is not /// available. @@ -65,79 +87,87 @@ mod zstd_compression { } } -/// A generic wrapper for a type that includes a compression ratio and encoded bytes. +/// A generic wrapper for a type that includes compression info and encoded bytes. #[derive(Debug, Clone)] -pub struct WithCompressionRatio { +pub struct WithCompressionInfo { // The original value. value: T, // The compression ratio: - // compression_ratio = max(1, size(v) * 1e9 / size(compress(v))) + // compression_ratio = max(1, size(tx.data) * 1e9 / size(compress(tx.data))) compression_ratio: U256, + // The compressed size in bytes: + // compressed_size = min(size(zstd(rlp(tx))), size(rlp(tx))) + compressed_size: usize, // The raw encoded bytes of `value`, without compression. encoded_bytes: Bytes, } /// A trait for types that can be constructed from a transaction, -/// its sender, encoded bytes and compression ratio. -pub trait FromTxWithCompressionRatio { +/// its sender, encoded bytes, compression ratio, and compressed size. +pub trait FromTxWithCompressionInfo { /// Builds a `TxEnv` from a transaction, its sender, encoded transaction bytes, - /// and a compression ratio. - fn from_tx_with_compression_ratio( + /// its compression ratio, and compressed size. + fn from_tx_with_compression_info( tx: &Tx, sender: Address, encoded: Bytes, compression_ratio: Option, + compressed_size: Option, ) -> Self; } -impl FromTxWithCompressionRatio<&T> for TxEnv +impl FromTxWithCompressionInfo<&T> for TxEnv where - TxEnv: FromTxWithCompressionRatio, + TxEnv: FromTxWithCompressionInfo, { - fn from_tx_with_compression_ratio( + fn from_tx_with_compression_info( tx: &&T, sender: Address, encoded: Bytes, compression_ratio: Option, + compressed_size: Option, ) -> Self { - TxEnv::from_tx_with_compression_ratio(tx, sender, encoded, compression_ratio) + TxEnv::from_tx_with_compression_info(tx, sender, encoded, compression_ratio, compressed_size) } } -impl> ToTxEnv - for WithCompressionRatio> +impl> ToTxEnv + for WithCompressionInfo> { fn to_tx_env(&self) -> TxEnv { let recovered = &self.value; - TxEnv::from_tx_with_compression_ratio( + TxEnv::from_tx_with_compression_info( recovered.inner(), recovered.signer(), self.encoded_bytes.clone(), Some(self.compression_ratio), + Some(self.compressed_size), ) } } -impl> ToTxEnv - for WithCompressionRatio<&Recovered> +impl> ToTxEnv + for WithCompressionInfo<&Recovered> { fn to_tx_env(&self) -> TxEnv { let recovered = &self.value; - TxEnv::from_tx_with_compression_ratio( + TxEnv::from_tx_with_compression_info( recovered.inner(), *recovered.signer(), self.encoded_bytes.clone(), Some(self.compression_ratio), + Some(self.compressed_size), ) } } -impl FromTxWithCompressionRatio for ScrollTransactionIntoTxEnv { - fn from_tx_with_compression_ratio( +impl FromTxWithCompressionInfo for ScrollTransactionIntoTxEnv { + fn from_tx_with_compression_info( tx: &ScrollTxEnvelope, caller: Address, encoded: Bytes, compression_ratio: Option, + compressed_size: Option, ) -> Self { let base = match &tx { ScrollTxEnvelope::Legacy(tx) => TxEnv::from_recovered_tx(tx.tx(), caller), @@ -165,35 +195,38 @@ impl FromTxWithCompressionRatio for ScrollTransactionIntoTxEnv } }; - Self::new(base, Some(encoded), compression_ratio) + Self::new(base, Some(encoded), compression_ratio, compressed_size) } } -/// A trait that allows a type to be converted into [`WithCompressionRatio`]. -pub trait ToTxWithCompressionRatio { - /// Converts the type into a [`WithCompressionRatio`] instance using the provided compression - /// ratio. - fn with_compression_ratio( +/// A trait that allows a type to be converted into [`WithCompressionInfo`]. +pub trait ToTxWithCompressionInfo { + /// Converts the type into a [`WithCompressionInfo`] instance using the provided compression + /// ratio and compressed size. + fn with_compression_info( &self, compression_ratio: U256, - ) -> WithCompressionRatio>; + compressed_size: usize, + ) -> WithCompressionInfo>; } -impl ToTxWithCompressionRatio for Recovered<&Tx> { - fn with_compression_ratio( +impl ToTxWithCompressionInfo for Recovered<&Tx> { + fn with_compression_info( &self, compression_ratio: U256, - ) -> WithCompressionRatio> { + compressed_size: usize, + ) -> WithCompressionInfo> { let encoded_bytes = self.inner().encoded_2718(); - WithCompressionRatio { + WithCompressionInfo { value: *self, compression_ratio, + compressed_size, encoded_bytes: encoded_bytes.into(), } } } -impl> RecoveredTx for WithCompressionRatio { +impl> RecoveredTx for WithCompressionInfo { fn tx(&self) -> &Tx { self.value.tx() } @@ -205,51 +238,83 @@ impl> RecoveredTx for WithCompressionRatio { #[cfg(test)] mod tests { + use crate::compute_compressed_size; + use super::compute_compression_ratio; - use alloy_primitives::{bytes, U256}; + use alloy_primitives::{bytes, U256, uint}; #[test] fn test_compute_compression_ratio() -> eyre::Result<()> { // eth-transfer let bytes = bytes!("0x"); let ratio = compute_compression_ratio(&bytes); + let size = compute_compressed_size(&bytes); assert_eq!(ratio, U256::MAX); // empty data is infinitely compressible by definition + assert_eq!(size, 0); // scr-transfer // https://scrollscan.com/tx/0x7b681ce914c9774aff364d2b099b2ba41dea44bcd59dbebb9d4c4b6853893179 let bytes = bytes!("0xa9059cbb000000000000000000000000687b50a70d33d71f9a82dd330b8c091e4d77250800000000000000000000000000000000000000000000000ac96dda943e512bb9"); let ratio = compute_compression_ratio(&bytes); + let size = compute_compressed_size(&bytes); assert_eq!(ratio, U256::from(1_387_755_102u64)); // 1.4x + assert_eq!(size, 49); // syncswap-swap // https://scrollscan.com/tx/0x59a7b72503400b6719f3cb670c7b1e7e45ce5076f30b98bdaad3b07a5d0fbc02 let bytes = bytes!("0x2cc4081e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000005ec79b80000000000000000000000000000000000000000000000000003328b944c400000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000053000000000000000000000000000000000000040000000000000000000000000000000000000000000000000091a94863ca800000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000814a23b053fd0f102aeeda0459215c2444799c7000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000600000000000000000000000005300000000000000000000000000000000000004000000000000000000000000485ca81b70255da2fe3fd0814b57d1b08fce784e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000"); let ratio = compute_compression_ratio(&bytes); + let size = compute_compressed_size(&bytes); assert_eq!(ratio, U256::from(4_857_142_857u64)); // 4.8x + assert_eq!(size, 126); // uniswap-swap // https://scrollscan.com/tx/0x65b268bd8ef416f44983ee277d748de044243272b0f106b71ff03cc8501a05da let bytes = bytes!("0x5023b4df00000000000000000000000006efdbff2a14a7c8e15944d1f4a48f9f95f663a4000000000000000000000000530000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000485ca81b70255da2fe3fd0814b57d1b08fce784e000000000000000000000000000000000000000000000000006a94d74f43000000000000000000000000000000000000000000000000000000000000045af6750000000000000000000000000000000000000000000000000000000000000000"); let ratio = compute_compression_ratio(&bytes); + let size = compute_compressed_size(&bytes); assert_eq!(ratio, U256::from(2_620_689_655u64)); // 2.6x + assert_eq!(size, 87); // etherfi-deposit // https://scrollscan.com/tx/0x41a77736afd54134b6c673e967c9801e326495074012b4033bd557920cbe5a71 let bytes = bytes!("0x63baa26000000000000000000000000077a7e3215a621a9935d32a046212ebfcffa3bff900000000000000000000000006efdbff2a14a7c8e15944d1f4a48f9f95f663a400000000000000000000000008c6f91e2b681faf5e17227f2a44c307b3c1364c0000000000000000000000000000000000000000000000000000000002d4cae000000000000000000000000000000000000000000000000000000000028f7f83000000000000000000000000249e3fa81d73244f956ecd529715323b6d02f24b00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000041a95314c3a11f86cc673f2afd60d27f559cb2edcc0da5af030adffc97f9a5edc3314efbadd32878e289017f644a4afa365da5367fefe583f7c4ff0c6047e2c1ff1b00000000000000000000000000000000000000000000000000000000000000"); let ratio = compute_compression_ratio(&bytes); + let size = compute_compressed_size(&bytes); assert_eq!(ratio, U256::from(1_788_944_723u64)); // 1.8x + assert_eq!(size, 199); + + // etherfi-stargate + // https://scrollscan.com/tx/0x08bf18e860d4770920ba838fe709ca202227aa9afea1b0c11314e7f41fc5f578 + let bytes = bytes!("0x5988e7a1000000000000000000000000388325dd7c76e37cfda1ed6d8a97849a46b5512a"); + let ratio = compute_compression_ratio(&bytes); + let size = compute_compressed_size(&bytes); + assert_eq!(ratio, U256::from(1_000_000_000)); // 1x + assert_eq!(size, 36); + + // etherfi-openocean + // https://scrollscan.com/tx/0xba29777d4135cb1b1dc462f07d486ad589dd3de74b8a5a64e9ff070cef0db35a + let bytes = bytes!("0x052fc63500000000000000000000000088c6e32066a5ae1dba00b2ea064d30c22a21f847000000000000000000000000d29687c813d741e2f938f4ac377128810e217b1b000000000000000000000000f55bec9cafdbe8730f096aa55dad6d22d44099df0000000000000000000000000000000000000000000000051e17bd1af1999e070000000000000000000000000000000000000000000000000000000000ccefaf0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000204000000000000000000000000000000000000000000000000000000000000020800000000000000000000000000000000000000000000000000000000000001f0490411a320000000000000000000000001aa298ae7c53d8dafa200ed49608649bfa76a446000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000d29687c813d741e2f938f4ac377128810e217b1b000000000000000000000000f55bec9cafdbe8730f096aa55dad6d22d44099df0000000000000000000000001aa298ae7c53d8dafa200ed49608649bfa76a44600000000000000000000000088c6e32066a5ae1dba00b2ea064d30c22a21f8470000000000000000000000000000000000000000000000051e17bd1af1999e070000000000000000000000000000000000000000000000000000000000ccefaf0000000000000000000000000000000000000000000000000000000000cf019f00000000000000000000000000000000000000000000000000000000000000020000000000000000000000002e0be8d3d9f1833fbacf9a5e9f2d470817ff0c0000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000ba00000000000000000000000000000000000000000000000000000000000000d8000000000000000000000000000000000000000000000000000000000000011c000000000000000000000000000000000000000000000000000000000000013a000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000019a00000000000000000000000000000000000000000000000000000000000001ac000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064eb5625d9000000000000000000000000d29687c813d741e2f938f4ac377128810e217b1b0000000000000000000000007160570bb153edd0ea1775ec2b2ac9b65f1ab61b000000000000000000000000000000000000000000000004e9b0639efc6a8339000000000000000000000000000000000000000000000000000000000000000000000000000000007160570bb153edd0ea1775ec2b2ac9b65f1ab61b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064511de15b000000000000000000000000d29687c813d741e2f938f4ac377128810e217b1b000000000000000000000000054641825533d1bc3324df3c30cbc3baea812087000000000000000000000000000000000000000000000004e9b0639efc6a833900000000000000000000000000000000000000000000000000000000000000000000000000000000054641825533d1bc3324df3c30cbc3baea81208700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001247132bb7f00000000000000000000000000000000000000000000000000000000000000800000000000000000000000001aa298ae7c53d8dafa200ed49608649bfa76a446000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000d29687c813d741e2f938f4ac377128810e217b1b0000000000000000000000001aa298ae7c53d8dafa200ed49608649bfa76a4460000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001a49f865422000000000000000000000000d29687c813d741e2f938f4ac377128810e217b1b00000000000000000000000000000001000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d1660f99000000000000000000000000d29687c813d741e2f938f4ac377128810e217b1b000000000000000000000000940f31ea73bfea357354b0263b92f3ba70eb3b6100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000643afe5f008000000000000000186a00b4940f31ea73bfea357354b0263b92f3ba70eb3b61000000000000000000000000d29687c813d741e2f938f4ac377128810e217b1b0000000000000000000000001aa298ae7c53d8dafa200ed49608649bfa76a44600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001a49f865422000000000000000000000000d29687c813d741e2f938f4ac377128810e217b1b00000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d1660f99000000000000000000000000d29687c813d741e2f938f4ac377128810e217b1b00000000000000000000000095b0c398cf6d296faa551291a9f3bf02a68c7a300000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000095b0c398cf6d296faa551291a9f3bf02a68c7a3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001247132bb7f00000000000000000000000000000000000000000000000000000000000000800000000000000000000000001aa298ae7c53d8dafa200ed49608649bfa76a446000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000d29687c813d741e2f938f4ac377128810e217b1b0000000000000000000000001aa298ae7c53d8dafa200ed49608649bfa76a44600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000038451a74316000000000000000000000000530000000000000000000000000000000000000400000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064eb5625d900000000000000000000000053000000000000000000000000000000000000040000000000000000000000007160570bb153edd0ea1775ec2b2ac9b65f1ab61b0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000007160570bb153edd0ea1775ec2b2ac9b65f1ab61b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064511de15b0000000000000000000000005300000000000000000000000000000000000004000000000000000000000000814a23b053fd0f102aeeda0459215c2444799c7000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000000000000000000000814a23b053fd0f102aeeda0459215c2444799c7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001247132bb7f00000000000000000000000000000000000000000000000000000000000000800000000000000000000000001aa298ae7c53d8dafa200ed49608649bfa76a44600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000006000000000000000000000000053000000000000000000000000000000000000040000000000000000000000001aa298ae7c53d8dafa200ed49608649bfa76a4460000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002449f86542200000000000000000000000006efdbff2a14a7c8e15944d1f4a48f9f95f663a4000000000000000000000000000000140000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000024000000000000000000000000882f1fdd5e320e39b6baa8317ec6f0171d1f499800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001043eece7db0000000000000000000000001aa298ae7c53d8dafa200ed49608649bfa76a446000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000a7e848aca42d879ef06507fca0e7b33a0a63c1e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002449f86542200000000000000000000000006efdbff2a14a7c8e15944d1f4a48f9f95f663a400000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000104e5b07cdb000000000000000000000000f1783f3377b3a70465c193ef33942c0803121ba0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000001aa298ae7c53d8dafa200ed49608649bfa76a44600000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002e06efdbff2a14a7c8e15944d1f4a48f9f95f663a4000064f55bec9cafdbe8730f096aa55dad6d22d44099df0000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000648a6a1e85000000000000000000000000f55bec9cafdbe8730f096aa55dad6d22d44099df000000000000000000000000922164bbbd36acf9e854acbbf32facc949fcaeef0000000000000000000000000000000000000000000000000000000000cf019f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001a49f865422000000000000000000000000f55bec9cafdbe8730f096aa55dad6d22d44099df00000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d1660f99000000000000000000000000f55bec9cafdbe8730f096aa55dad6d22d44099df00000000000000000000000088c6e32066a5ae1dba00b2ea064d30c22a21f84700000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000ba5f8a00c2032c01bd7ed4fb2f3c8e95982539bd000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041eacb429b4309061c97d928fa5d671b6b881dc7f959fe98efcd40e6a749866ab7000ba6acb9da5d2268f4d2acd12164f9036995428dc9cdad753fe205e0ab00da1b00000000000000000000000000000000000000000000000000000000000000"); + let ratio = compute_compression_ratio(&bytes); + let size = compute_compressed_size(&bytes); + assert_eq!(ratio, uint!(8_992_608_236_U256)); // 9x + assert_eq!(size, 947); // edgepushoracle-postupdate // https://scrollscan.com/tx/0x8271c68146a3b07b1ebf52ce0b550751f49cbd72fa0596ef14ff56d1f23a0bec let bytes = bytes!("0x49a1a4fb000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000005f725f60000000000000000000000000000000000000000000000000000000003d0cac600000000000000000000000000000000000000000000000000000000685d50cd000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000004155903b95865fc5a5dd7d4d876456140dd0b815695647fc41eb1924f4cfe267265130b5a5d77125c44cf6a5a81edba6d5850ba00f90ab83281c9b44e17528fd74010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000416f000e0498733998e6a1a6454e116c1b1f95f7e000400b6a54029406cf288bdc615b62de8e2db533d6010ca57001e0b8a4b3f05ed516a31830516c52b9df206e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410dabc77a807d729ff62c3be740d492d884f026ad2770fa7c4bdec569e201643656b07f2009d2129173738571417734a3df051cebc7b8233bec6d9471c21c098700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041eb009614c939170e9ff3d3e06c3a2c45810fe46a364ce28ecec5e220f5fd86cd6e0f70ab9093dd6b22b69980246496b600c8fcb054047962d4128efa48b692f301000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041a31b4dd4f0a482372d75c7a8c5f11aa8084a5f358579866f1d25a26a15beb2b5153400bfa7fa3d6fba138c02dd1eb8a5a97d62178d98c5632a153396a566e5ed0000000000000000000000000000000000000000000000000000000000000000"); let ratio = compute_compression_ratio(&bytes); + let size = compute_compressed_size(&bytes); assert_eq!(ratio, U256::from(2_441_805_225u64)); // 2.4x + assert_eq!(size, 421); // intmax-post // https://scrollscan.com/tx/0x7244e27223cdd79ba0f0e3990c746e5d524e35dbcc200f0a7e664ffdc6d08eef let bytes = bytes!("0x9b6babf0f0372bb253e060ecbdd3dbef8b832b0e743148bd807bfcf665593a56a18bac69000000000000000000000000000000000000000000000000000000006861676d0000000000000000000000000000000000000000000000000000000000000015800000000000000000000000000000000000000000000000000000000000000029a690c4ef1e18884a11f73c8595fb721f964a3e2bee809800c474278f024bcd05a76119827e6c464cee8620f616a9a23d41305eb9f9682f9d2eaf964325fcd71147783453566f27ce103a2398d96719ee22ba51b89b92cdf952af817929329403b75ae310b23cf250041d53c82bef431fa2527e2dd68b49f45f06feb2bd09f011358fe2650b8987ea2bb39bb6e28ce770f4fc9c4f064d0ae7573a1450452b501a5b0d3454d254dbf9db7094f4ca1f5056143f5c70dee4126443a6150d9e51bd05dac7e9a2bd48a8797ac6e9379d400c5ce1815b10846eaf0d80dca3a727ffd0075387e0f1bc1b363c81ecf8d05a4b654ac6fbe1cdc7c741a5c0bbeabde4138906009129ca033af12094fd7306562d9735b2fe757f021b7eb3320f8a814a286a10130969de2783e49871b80e967cfba630e6bdef2fd1d2b1076c6c3f5fd9ae5800000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000012a98f1556efe81340fad3e59044b8139ce62f1d5d50b44b680de9422b1ddbf1a"); let ratio = compute_compression_ratio(&bytes); + let size = compute_compressed_size(&bytes); assert_eq!(ratio, U256::from(1_298_578_199u64)); // 1.3x + assert_eq!(size, 422); Ok(()) } diff --git a/crates/scroll/alloy/evm/src/tx/mod.rs b/crates/scroll/alloy/evm/src/tx/mod.rs index c8c921d1d3b..da6c3080bd3 100644 --- a/crates/scroll/alloy/evm/src/tx/mod.rs +++ b/crates/scroll/alloy/evm/src/tx/mod.rs @@ -13,8 +13,8 @@ use scroll_alloy_consensus::{ScrollTxEnvelope, TxL1Message, L1_MESSAGE_TRANSACTI mod compression; pub use compression::{ - compute_compression_ratio, FromTxWithCompressionRatio, ToTxWithCompressionRatio, - WithCompressionRatio, + compute_compression_ratio, compute_compressed_size, FromTxWithCompressionInfo, ToTxWithCompressionInfo, + WithCompressionInfo, }; /// This structure wraps around a [`ScrollTransaction`] and allows us to implement the [`IntoTxEnv`] @@ -27,8 +27,8 @@ pub struct ScrollTransactionIntoTxEnv(ScrollTransaction); impl ScrollTransactionIntoTxEnv { /// Returns a new [`ScrollTransactionIntoTxEnv`]. - pub fn new(base: T, rlp_bytes: Option, compression_ratio: Option) -> Self { - Self(ScrollTransaction::new(base, rlp_bytes, compression_ratio)) + pub fn new(base: T, rlp_bytes: Option, compression_ratio: Option, compressed_size: Option) -> Self { + Self(ScrollTransaction::new(base, rlp_bytes, compression_ratio, compressed_size)) } } @@ -166,11 +166,16 @@ impl FromTxWithEncoded for ScrollTransactionIntoTxEnv { } }; - let encoded = (!tx.is_l1_message()).then_some(encoded); - // Note: We compute the transaction ratio on tx.data, not on the full encoded transaction. - let compression_ratio = - (!tx.is_l1_message()).then(|| compute_compression_ratio(base.input())); - Self::new(base, encoded, compression_ratio) + let (encoded, compression_ratio, compressed_size) = match tx { + ScrollTxEnvelope::L1Message(_) => (None, None, None), + _ => { + let ratio = compute_compression_ratio(base.input()); // compute on tx data + let size = compute_compressed_size(&encoded); // compute on rlp-encoded tx + (Some(encoded), Some(ratio), Some(size)) + } + }; + + Self::new(base, encoded, compression_ratio, compressed_size) } } @@ -276,11 +281,16 @@ impl FromRecoveredTx for ScrollTransactionIntoTxEnv { }, }; - let encoded = (!tx.is_l1_message()).then_some(envelope.into()); - // Note: We compute the transaction ratio on tx.data, not on the full encoded transaction. - let compression_ratio = - (!tx.is_l1_message()).then(|| compute_compression_ratio(base.input())); + let (encoded, compression_ratio, compressed_size) = match tx { + ScrollTxEnvelope::L1Message(_) => (None, None, None), + _ => { + let encoded = envelope.into(); + let ratio = compute_compression_ratio(base.input()); // compute on tx data + let size = compute_compressed_size(&encoded); // compute on rlp-encoded tx + (Some(encoded), Some(ratio), Some(size)) + } + }; - Self::new(base, encoded, compression_ratio) + Self::new(base, encoded, compression_ratio, compressed_size) } } diff --git a/crates/scroll/evm/src/execute.rs b/crates/scroll/evm/src/execute.rs index 56a7dad3c21..4872b1b31f4 100644 --- a/crates/scroll/evm/src/execute.rs +++ b/crates/scroll/evm/src/execute.rs @@ -49,8 +49,7 @@ mod tests { Block, BlockBody, Header, SignableTransaction, Signed, Transaction, TxLegacy, }; use alloy_eips::{ - eip7702::{constants::PER_EMPTY_ACCOUNT_COST, Authorization, SignedAuthorization}, - Typed2718, + Encodable2718, Typed2718, eip7702::{Authorization, SignedAuthorization, constants::PER_EMPTY_ACCOUNT_COST} }; use alloy_evm::{ block::{BlockExecutionResult, BlockExecutor}, @@ -78,6 +77,7 @@ mod tests { use scroll_alloy_consensus::{ScrollTransactionReceipt, ScrollTxEnvelope, ScrollTxType}; use scroll_alloy_evm::{ compute_compression_ratio, + compute_compressed_size, curie::{ BLOB_SCALAR_SLOT, COMMIT_SCALAR_SLOT, CURIE_L1_GAS_PRICE_ORACLE_BYTECODE, CURIE_L1_GAS_PRICE_ORACLE_STORAGE, IS_CURIE_SLOT, L1_BLOB_BASE_FEE_SLOT, @@ -222,7 +222,7 @@ mod tests { transactions: Vec, block_number: u64, block_timestamp: u64, - compression_ratios: Option>, + compression_infos: Option>, // (compression ratio, compressed size) pairs ) -> eyre::Result> { let block = block(block_number, block_timestamp, transactions); @@ -277,10 +277,10 @@ mod tests { .insert_account(*add, AccountInfo { balance: U256::MAX, ..Default::default() }); } - if let Some(compression_ratios) = compression_ratios { + if let Some(compression_infos) = compression_infos { Ok(strategy.execute_block_with_compression_cache( block.transactions_recovered(), - compression_ratios, + compression_infos, )?) } else { Ok(strategy.execute_block(block.transactions_recovered())?) @@ -654,17 +654,17 @@ mod tests { transaction(ScrollTxType::Eip1559, MIN_TRANSACTION_GAS), transaction(ScrollTxType::Eip7702, MIN_TRANSACTION_GAS), ]; - let compression_ratios = - transactions.iter().map(|tx| compute_compression_ratio(tx.input())).collect::>(); - let with_compression_ratios = execute_block( + let compression_infos = + transactions.iter().map(|tx| (compute_compression_ratio(tx.input()), compute_compressed_size(&tx.encoded_2718()))).collect::>(); + let with_compression_infos = execute_block( transactions.clone(), CURIE_BLOCK_NUMBER + 1, FEYNMAN_BLOCK_TIMESTAMP, - Some(compression_ratios), + Some(compression_infos), )?; - let without_compression_ratios = + let without_compression_infos = execute_block(transactions, CURIE_BLOCK_NUMBER + 1, FEYNMAN_BLOCK_TIMESTAMP, None)?; - assert_eq!(without_compression_ratios, with_compression_ratios); + assert_eq!(without_compression_infos, with_compression_infos); Ok(()) } } diff --git a/crates/scroll/evm/src/l1.rs b/crates/scroll/evm/src/l1.rs index 2ad06a3839c..e27acf51cfb 100644 --- a/crates/scroll/evm/src/l1.rs +++ b/crates/scroll/evm/src/l1.rs @@ -22,6 +22,7 @@ pub trait RethL1BlockInfo { block: u64, input: &[u8], compression_ratio: Option, + compressed_size: Option, is_l1_message: bool, ) -> Result; } @@ -34,6 +35,7 @@ impl RethL1BlockInfo for L1BlockInfo { block_number: u64, input: &[u8], compression_ratio: Option, + compressed_size: Option, is_l1_message: bool, ) -> Result { if is_l1_message { @@ -41,6 +43,6 @@ impl RethL1BlockInfo for L1BlockInfo { } let spec_id = spec_id_at_timestamp_and_number(timestamp, block_number, chain_spec); - Ok(self.calculate_tx_l1_cost(input, spec_id, compression_ratio)) + Ok(self.calculate_tx_l1_cost(input, spec_id, compression_ratio, compressed_size)) } } diff --git a/crates/scroll/evm/src/lib.rs b/crates/scroll/evm/src/lib.rs index d8135610e1f..108b0ce01cc 100644 --- a/crates/scroll/evm/src/lib.rs +++ b/crates/scroll/evm/src/lib.rs @@ -35,8 +35,8 @@ use reth_scroll_chainspec::ScrollChainSpec; use reth_scroll_primitives::ScrollPrimitives; use revm_scroll::ScrollSpecId; pub use scroll_alloy_evm::{ - compute_compression_ratio, ScrollBlockExecutorFactory, ScrollDefaultPrecompilesFactory, - ScrollEvmFactory, ScrollTxCompressionRatios, + compute_compression_ratio, compute_compressed_size, ScrollBlockExecutorFactory, ScrollDefaultPrecompilesFactory, + ScrollEvmFactory, ScrollTxCompressionInfos, }; pub use scroll_alloy_hardforks::{ScrollHardfork, ScrollHardforks}; diff --git a/crates/scroll/txpool/src/validator.rs b/crates/scroll/txpool/src/validator.rs index 7060a1a6247..4b775acd28f 100644 --- a/crates/scroll/txpool/src/validator.rs +++ b/crates/scroll/txpool/src/validator.rs @@ -8,7 +8,7 @@ use reth_primitives_traits::{ use reth_revm::database::StateProviderDatabase; use reth_scroll_consensus::MAX_ROLLUP_FEE; use reth_scroll_evm::{ - compute_compression_ratio, spec_id_at_timestamp_and_number, RethL1BlockInfo, + compute_compression_ratio, compute_compressed_size, spec_id_at_timestamp_and_number, RethL1BlockInfo, }; use reth_scroll_forks::ScrollHardforks; use reth_storage_api::{BlockReaderIdExt, StateProviderFactory}; @@ -177,7 +177,11 @@ where let mut encoded = Vec::with_capacity(valid_tx.transaction().encoded_length()); let tx = valid_tx.transaction().clone_into_consensus(); tx.encode_2718(&mut encoded); + + // Note, compression ratio is computed on tx.input, + // while compressed size is computed on the full encoded transaction. let compression_ratio = compute_compression_ratio(valid_tx.transaction().input()); + let compressed_size = compute_compressed_size(&encoded); let cost_addition = match l1_block_info.l1_tx_data_fee( self.chain_spec(), @@ -185,6 +189,7 @@ where self.block_number(), &encoded, Some(compression_ratio), + Some(compressed_size), false, ) { Ok(cost) => cost, From 1f7f296623dd50b69e83f281d8e8796ac1a7a29c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 5 Nov 2025 11:34:13 +0100 Subject: [PATCH 2/5] lint --- crates/scroll/alloy/evm/src/block/mod.rs | 3 +- crates/scroll/alloy/evm/src/lib.rs | 4 +-- crates/scroll/alloy/evm/src/tx/compression.rs | 29 ++++++++++++------- crates/scroll/alloy/evm/src/tx/mod.rs | 11 +++++-- crates/scroll/evm/src/execute.rs | 17 +++++++---- crates/scroll/evm/src/l1.rs | 13 ++++++--- crates/scroll/evm/src/lib.rs | 4 +-- crates/scroll/txpool/src/validator.rs | 6 ++-- 8 files changed, 55 insertions(+), 32 deletions(-) diff --git a/crates/scroll/alloy/evm/src/block/mod.rs b/crates/scroll/alloy/evm/src/block/mod.rs index a94cb311803..663cfd27342 100644 --- a/crates/scroll/alloy/evm/src/block/mod.rs +++ b/crates/scroll/alloy/evm/src/block/mod.rs @@ -123,7 +123,8 @@ where { self.apply_pre_execution_changes()?; - for (tx, (compression_ratio, compressed_size)) in transactions.into_iter().zip(compression_infos.into_iter()) + for (tx, (compression_ratio, compressed_size)) in + transactions.into_iter().zip(compression_infos.into_iter()) { let tx = tx.with_compression_info(compression_ratio, compressed_size); self.execute_transaction(&tx)?; diff --git a/crates/scroll/alloy/evm/src/lib.rs b/crates/scroll/alloy/evm/src/lib.rs index 48fba905870..f16c7ef8776 100644 --- a/crates/scroll/alloy/evm/src/lib.rs +++ b/crates/scroll/alloy/evm/src/lib.rs @@ -12,8 +12,8 @@ pub use block::{ mod tx; pub use tx::{ - compute_compression_ratio, compute_compressed_size, FromTxWithCompressionInfo, ScrollTransactionIntoTxEnv, - ToTxWithCompressionInfo, WithCompressionInfo, + compute_compressed_size, compute_compression_ratio, FromTxWithCompressionInfo, + ScrollTransactionIntoTxEnv, ToTxWithCompressionInfo, WithCompressionInfo, }; mod system_caller; diff --git a/crates/scroll/alloy/evm/src/tx/compression.rs b/crates/scroll/alloy/evm/src/tx/compression.rs index cf0eefb5b53..f009021c3b0 100644 --- a/crates/scroll/alloy/evm/src/tx/compression.rs +++ b/crates/scroll/alloy/evm/src/tx/compression.rs @@ -6,7 +6,7 @@ use alloy_evm::{RecoveredTx, ToTxEnv}; use alloy_primitives::{Address, Bytes, TxKind, U256}; use revm::context::TxEnv; use scroll_alloy_consensus::{ScrollTxEnvelope, TxL1Message}; -pub use zstd_compression::{compute_compression_ratio, compute_compressed_size}; +pub use zstd_compression::{compute_compressed_size, compute_compression_ratio}; #[cfg(feature = "zstd_compression")] mod zstd_compression { @@ -41,7 +41,11 @@ mod zstd_compression { let result = compressor.finish().expect("failed to finish compression"); let encoded_bytes_len = result.len(); - if encoded_bytes_len > original_bytes_len { original_bytes_len } else { encoded_bytes_len } + if encoded_bytes_len > original_bytes_len { + original_bytes_len + } else { + encoded_bytes_len + } } /// Computes the compression ratio for the provided bytes. @@ -127,13 +131,17 @@ where compression_ratio: Option, compressed_size: Option, ) -> Self { - TxEnv::from_tx_with_compression_info(tx, sender, encoded, compression_ratio, compressed_size) + TxEnv::from_tx_with_compression_info( + tx, + sender, + encoded, + compression_ratio, + compressed_size, + ) } } -impl> ToTxEnv - for WithCompressionInfo> -{ +impl> ToTxEnv for WithCompressionInfo> { fn to_tx_env(&self) -> TxEnv { let recovered = &self.value; TxEnv::from_tx_with_compression_info( @@ -146,9 +154,7 @@ impl> ToTxEnv } } -impl> ToTxEnv - for WithCompressionInfo<&Recovered> -{ +impl> ToTxEnv for WithCompressionInfo<&Recovered> { fn to_tx_env(&self) -> TxEnv { let recovered = &self.value; TxEnv::from_tx_with_compression_info( @@ -241,7 +247,7 @@ mod tests { use crate::compute_compressed_size; use super::compute_compression_ratio; - use alloy_primitives::{bytes, U256, uint}; + use alloy_primitives::{bytes, uint, U256}; #[test] fn test_compute_compression_ratio() -> eyre::Result<()> { @@ -286,7 +292,8 @@ mod tests { // etherfi-stargate // https://scrollscan.com/tx/0x08bf18e860d4770920ba838fe709ca202227aa9afea1b0c11314e7f41fc5f578 - let bytes = bytes!("0x5988e7a1000000000000000000000000388325dd7c76e37cfda1ed6d8a97849a46b5512a"); + let bytes = + bytes!("0x5988e7a1000000000000000000000000388325dd7c76e37cfda1ed6d8a97849a46b5512a"); let ratio = compute_compression_ratio(&bytes); let size = compute_compressed_size(&bytes); assert_eq!(ratio, U256::from(1_000_000_000)); // 1x diff --git a/crates/scroll/alloy/evm/src/tx/mod.rs b/crates/scroll/alloy/evm/src/tx/mod.rs index da6c3080bd3..2e3698a30d1 100644 --- a/crates/scroll/alloy/evm/src/tx/mod.rs +++ b/crates/scroll/alloy/evm/src/tx/mod.rs @@ -13,8 +13,8 @@ use scroll_alloy_consensus::{ScrollTxEnvelope, TxL1Message, L1_MESSAGE_TRANSACTI mod compression; pub use compression::{ - compute_compression_ratio, compute_compressed_size, FromTxWithCompressionInfo, ToTxWithCompressionInfo, - WithCompressionInfo, + compute_compressed_size, compute_compression_ratio, FromTxWithCompressionInfo, + ToTxWithCompressionInfo, WithCompressionInfo, }; /// This structure wraps around a [`ScrollTransaction`] and allows us to implement the [`IntoTxEnv`] @@ -27,7 +27,12 @@ pub struct ScrollTransactionIntoTxEnv(ScrollTransaction); impl ScrollTransactionIntoTxEnv { /// Returns a new [`ScrollTransactionIntoTxEnv`]. - pub fn new(base: T, rlp_bytes: Option, compression_ratio: Option, compressed_size: Option) -> Self { + pub fn new( + base: T, + rlp_bytes: Option, + compression_ratio: Option, + compressed_size: Option, + ) -> Self { Self(ScrollTransaction::new(base, rlp_bytes, compression_ratio, compressed_size)) } } diff --git a/crates/scroll/evm/src/execute.rs b/crates/scroll/evm/src/execute.rs index 4872b1b31f4..e31d104ba2a 100644 --- a/crates/scroll/evm/src/execute.rs +++ b/crates/scroll/evm/src/execute.rs @@ -49,7 +49,8 @@ mod tests { Block, BlockBody, Header, SignableTransaction, Signed, Transaction, TxLegacy, }; use alloy_eips::{ - Encodable2718, Typed2718, eip7702::{Authorization, SignedAuthorization, constants::PER_EMPTY_ACCOUNT_COST} + eip7702::{constants::PER_EMPTY_ACCOUNT_COST, Authorization, SignedAuthorization}, + Encodable2718, Typed2718, }; use alloy_evm::{ block::{BlockExecutionResult, BlockExecutor}, @@ -76,8 +77,7 @@ mod tests { }; use scroll_alloy_consensus::{ScrollTransactionReceipt, ScrollTxEnvelope, ScrollTxType}; use scroll_alloy_evm::{ - compute_compression_ratio, - compute_compressed_size, + compute_compressed_size, compute_compression_ratio, curie::{ BLOB_SCALAR_SLOT, COMMIT_SCALAR_SLOT, CURIE_L1_GAS_PRICE_ORACLE_BYTECODE, CURIE_L1_GAS_PRICE_ORACLE_STORAGE, IS_CURIE_SLOT, L1_BLOB_BASE_FEE_SLOT, @@ -222,7 +222,8 @@ mod tests { transactions: Vec, block_number: u64, block_timestamp: u64, - compression_infos: Option>, // (compression ratio, compressed size) pairs + compression_infos: Option>, /* (compression ratio, compressed size) + * pairs */ ) -> eyre::Result> { let block = block(block_number, block_timestamp, transactions); @@ -654,8 +655,12 @@ mod tests { transaction(ScrollTxType::Eip1559, MIN_TRANSACTION_GAS), transaction(ScrollTxType::Eip7702, MIN_TRANSACTION_GAS), ]; - let compression_infos = - transactions.iter().map(|tx| (compute_compression_ratio(tx.input()), compute_compressed_size(&tx.encoded_2718()))).collect::>(); + let compression_infos = transactions + .iter() + .map(|tx| { + (compute_compression_ratio(tx.input()), compute_compressed_size(&tx.encoded_2718())) + }) + .collect::>(); let with_compression_infos = execute_block( transactions.clone(), CURIE_BLOCK_NUMBER + 1, diff --git a/crates/scroll/evm/src/l1.rs b/crates/scroll/evm/src/l1.rs index e27acf51cfb..27cf4636405 100644 --- a/crates/scroll/evm/src/l1.rs +++ b/crates/scroll/evm/src/l1.rs @@ -14,6 +14,8 @@ pub trait RethL1BlockInfo { /// - `timestamp`: The timestamp of the current block. /// - `block`: The block number of the current block. /// - `input`: The calldata of the transaction. + /// - `compression_info`: An optional tuple containing the compression ratio and compressed + /// size. /// - `is_l1_message`: Whether or not the transaction is a l1 message. fn l1_tx_data_fee( &mut self, @@ -21,8 +23,7 @@ pub trait RethL1BlockInfo { timestamp: u64, block: u64, input: &[u8], - compression_ratio: Option, - compressed_size: Option, + compression_info: Option<(U256, usize)>, is_l1_message: bool, ) -> Result; } @@ -34,14 +35,18 @@ impl RethL1BlockInfo for L1BlockInfo { timestamp: u64, block_number: u64, input: &[u8], - compression_ratio: Option, - compressed_size: Option, + compression_info: Option<(U256, usize)>, is_l1_message: bool, ) -> Result { if is_l1_message { return Ok(U256::ZERO); } + let (compression_ratio, compressed_size) = match compression_info { + Some((ratio, size)) => (Some(ratio), Some(size)), + None => (None, None), + }; + let spec_id = spec_id_at_timestamp_and_number(timestamp, block_number, chain_spec); Ok(self.calculate_tx_l1_cost(input, spec_id, compression_ratio, compressed_size)) } diff --git a/crates/scroll/evm/src/lib.rs b/crates/scroll/evm/src/lib.rs index 108b0ce01cc..5ae4eae077a 100644 --- a/crates/scroll/evm/src/lib.rs +++ b/crates/scroll/evm/src/lib.rs @@ -35,8 +35,8 @@ use reth_scroll_chainspec::ScrollChainSpec; use reth_scroll_primitives::ScrollPrimitives; use revm_scroll::ScrollSpecId; pub use scroll_alloy_evm::{ - compute_compression_ratio, compute_compressed_size, ScrollBlockExecutorFactory, ScrollDefaultPrecompilesFactory, - ScrollEvmFactory, ScrollTxCompressionInfos, + compute_compressed_size, compute_compression_ratio, ScrollBlockExecutorFactory, + ScrollDefaultPrecompilesFactory, ScrollEvmFactory, ScrollTxCompressionInfos, }; pub use scroll_alloy_hardforks::{ScrollHardfork, ScrollHardforks}; diff --git a/crates/scroll/txpool/src/validator.rs b/crates/scroll/txpool/src/validator.rs index 4b775acd28f..65cead657ee 100644 --- a/crates/scroll/txpool/src/validator.rs +++ b/crates/scroll/txpool/src/validator.rs @@ -8,7 +8,8 @@ use reth_primitives_traits::{ use reth_revm::database::StateProviderDatabase; use reth_scroll_consensus::MAX_ROLLUP_FEE; use reth_scroll_evm::{ - compute_compression_ratio, compute_compressed_size, spec_id_at_timestamp_and_number, RethL1BlockInfo, + compute_compressed_size, compute_compression_ratio, spec_id_at_timestamp_and_number, + RethL1BlockInfo, }; use reth_scroll_forks::ScrollHardforks; use reth_storage_api::{BlockReaderIdExt, StateProviderFactory}; @@ -188,8 +189,7 @@ where self.block_timestamp(), self.block_number(), &encoded, - Some(compression_ratio), - Some(compressed_size), + Some((compression_ratio, compressed_size)), false, ) { Ok(cost) => cost, From 8329fc9ac0325368379d65e74cadf9e137358431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 5 Nov 2025 11:43:40 +0100 Subject: [PATCH 3/5] refactor, and fix ci --- crates/scroll/alloy/evm/src/block/mod.rs | 7 +++++-- crates/scroll/alloy/evm/src/lib.rs | 3 ++- crates/scroll/evm/src/execute.rs | 5 ++--- crates/scroll/evm/src/l1.rs | 8 ++++---- crates/scroll/openvm-compat/Cargo.lock | 2 +- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/crates/scroll/alloy/evm/src/block/mod.rs b/crates/scroll/alloy/evm/src/block/mod.rs index 663cfd27342..6b221ff1506 100644 --- a/crates/scroll/alloy/evm/src/block/mod.rs +++ b/crates/scroll/alloy/evm/src/block/mod.rs @@ -39,8 +39,11 @@ use revm_scroll::builder::ScrollContext; use scroll_alloy_consensus::L1_MESSAGE_TRANSACTION_TYPE; use scroll_alloy_hardforks::{ScrollHardfork, ScrollHardforks}; +/// Compression info is a pair of (compression ratio, compressed size). +pub type ScrollTxCompressionInfo = (U256, usize); + /// A cache for transaction compression infos, i.e. (compression ratio, compressed size) pairs. -pub type ScrollTxCompressionInfos = Vec<(U256, usize)>; +pub type ScrollTxCompressionInfos = Vec; /// Context for Scroll Block Execution. #[derive(Debug, Default, Clone)] @@ -116,7 +119,7 @@ where Item = impl ExecutableTx + ToTxWithCompressionInfo<::Transaction>, >, - compression_infos: impl IntoIterator, + compression_infos: impl IntoIterator, ) -> Result, BlockExecutionError> where Self: Sized, diff --git a/crates/scroll/alloy/evm/src/lib.rs b/crates/scroll/alloy/evm/src/lib.rs index f16c7ef8776..f8a7fda6db6 100644 --- a/crates/scroll/alloy/evm/src/lib.rs +++ b/crates/scroll/alloy/evm/src/lib.rs @@ -7,7 +7,8 @@ mod block; pub use block::{ curie, feynman, EvmExt, ReceiptBuilderCtx, ScrollBlockExecutionCtx, ScrollBlockExecutor, - ScrollBlockExecutorFactory, ScrollReceiptBuilder, ScrollTxCompressionInfos, + ScrollBlockExecutorFactory, ScrollReceiptBuilder, ScrollTxCompressionInfo, + ScrollTxCompressionInfos, }; mod tx; diff --git a/crates/scroll/evm/src/execute.rs b/crates/scroll/evm/src/execute.rs index e31d104ba2a..384d848fd32 100644 --- a/crates/scroll/evm/src/execute.rs +++ b/crates/scroll/evm/src/execute.rs @@ -84,7 +84,7 @@ mod tests { L1_GAS_PRICE_ORACLE_ADDRESS, }, feynman::{IS_FEYNMAN_SLOT, PENALTY_FACTOR_SLOT, PENALTY_THRESHOLD_SLOT}, - ScrollBlockExecutionCtx, ScrollBlockExecutor, ScrollEvm, + ScrollBlockExecutionCtx, ScrollBlockExecutor, ScrollEvm, ScrollTxCompressionInfos, }; use scroll_alloy_hardforks::ScrollHardforks; @@ -222,8 +222,7 @@ mod tests { transactions: Vec, block_number: u64, block_timestamp: u64, - compression_infos: Option>, /* (compression ratio, compressed size) - * pairs */ + compression_infos: Option, ) -> eyre::Result> { let block = block(block_number, block_timestamp, transactions); diff --git a/crates/scroll/evm/src/l1.rs b/crates/scroll/evm/src/l1.rs index 27cf4636405..1e2934100f3 100644 --- a/crates/scroll/evm/src/l1.rs +++ b/crates/scroll/evm/src/l1.rs @@ -2,6 +2,7 @@ use super::spec_id_at_timestamp_and_number; use reth_evm::block::BlockExecutionError; use revm_primitives::U256; use revm_scroll::l1block::L1BlockInfo; +use scroll_alloy_evm::ScrollTxCompressionInfo; use scroll_alloy_hardforks::ScrollHardforks; /// An extension trait for [`L1BlockInfo`] that allows us to calculate the L1 cost of a transaction @@ -14,8 +15,7 @@ pub trait RethL1BlockInfo { /// - `timestamp`: The timestamp of the current block. /// - `block`: The block number of the current block. /// - `input`: The calldata of the transaction. - /// - `compression_info`: An optional tuple containing the compression ratio and compressed - /// size. + /// - `compression_info`: An optional (compression ratio, compressed size) pair. /// - `is_l1_message`: Whether or not the transaction is a l1 message. fn l1_tx_data_fee( &mut self, @@ -23,7 +23,7 @@ pub trait RethL1BlockInfo { timestamp: u64, block: u64, input: &[u8], - compression_info: Option<(U256, usize)>, + compression_info: Option, is_l1_message: bool, ) -> Result; } @@ -35,7 +35,7 @@ impl RethL1BlockInfo for L1BlockInfo { timestamp: u64, block_number: u64, input: &[u8], - compression_info: Option<(U256, usize)>, + compression_info: Option, is_l1_message: bool, ) -> Result { if is_l1_message { diff --git a/crates/scroll/openvm-compat/Cargo.lock b/crates/scroll/openvm-compat/Cargo.lock index 9571e97c6b0..f0977728d09 100644 --- a/crates/scroll/openvm-compat/Cargo.lock +++ b/crates/scroll/openvm-compat/Cargo.lock @@ -2985,7 +2985,7 @@ dependencies = [ [[package]] name = "revm-scroll" version = "0.1.0" -source = "git+https://github.com/scroll-tech/scroll-revm?branch=feat%2Fv87#6768f7859abe85c3146161f7026cab10751e1a50" +source = "git+https://github.com/scroll-tech/scroll-revm#c87b934962b84bcb6fda0fe49bd248d87ff6766e" dependencies = [ "auto_impl", "enumn", From 8a581dd58588c010821f4640f21d0449aa3bf1e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 5 Nov 2025 14:42:07 +0100 Subject: [PATCH 4/5] bump revm version --- Cargo.lock | 2 +- crates/scroll/openvm-compat/Cargo.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b49d5d44b25..b06585bd133 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11471,7 +11471,7 @@ dependencies = [ [[package]] name = "revm-scroll" version = "0.1.0" -source = "git+https://github.com/scroll-tech/scroll-revm#c87b934962b84bcb6fda0fe49bd248d87ff6766e" +source = "git+https://github.com/scroll-tech/scroll-revm#f5ae93d909f185461af8d0263b2549081e9781c8" dependencies = [ "auto_impl", "enumn", diff --git a/crates/scroll/openvm-compat/Cargo.lock b/crates/scroll/openvm-compat/Cargo.lock index f0977728d09..3bf6f91d724 100644 --- a/crates/scroll/openvm-compat/Cargo.lock +++ b/crates/scroll/openvm-compat/Cargo.lock @@ -2985,7 +2985,7 @@ dependencies = [ [[package]] name = "revm-scroll" version = "0.1.0" -source = "git+https://github.com/scroll-tech/scroll-revm#c87b934962b84bcb6fda0fe49bd248d87ff6766e" +source = "git+https://github.com/scroll-tech/scroll-revm#f5ae93d909f185461af8d0263b2549081e9781c8" dependencies = [ "auto_impl", "enumn", From 7150467fd6572de311da8125885de82200433c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 5 Nov 2025 14:46:48 +0100 Subject: [PATCH 5/5] add clarifying comment --- crates/scroll/alloy/evm/src/tx/compression.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/scroll/alloy/evm/src/tx/compression.rs b/crates/scroll/alloy/evm/src/tx/compression.rs index f009021c3b0..cb6492e4ca6 100644 --- a/crates/scroll/alloy/evm/src/tx/compression.rs +++ b/crates/scroll/alloy/evm/src/tx/compression.rs @@ -250,7 +250,13 @@ mod tests { use alloy_primitives::{bytes, uint, U256}; #[test] - fn test_compute_compression_ratio() -> eyre::Result<()> { + fn test_compression() -> eyre::Result<()> { + // Compute compression ratio and compressed size for each test case. + // These test cases are meant to be shared between the Go and Rust implementations. + // Note: Feynman's compression ratio is computed on the transaction payload, + // while Galileo's compressed size is computed on the full RLP-encoded transaction. + // In these compression tests we ignore this distinction. + // eth-transfer let bytes = bytes!("0x"); let ratio = compute_compression_ratio(&bytes);