Skip to content
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
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/scroll/alloy/evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ revm = { workspace = true, default-features = false, features = ["optional_no_ba

# scroll
revm-scroll = { workspace = true, default-features = false }
reth-scroll-chainspec = { workspace = true, default-features = false }

# scroll
scroll-alloy-consensus = { workspace = true, default-features = false }
Expand Down
21 changes: 14 additions & 7 deletions crates/scroll/alloy/evm/src/block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use alloy_evm::{
Database, Evm, EvmFactory, FromRecoveredTx, FromTxWithEncoded,
};
use alloy_primitives::{B256, U256};
use reth_scroll_chainspec::{ChainConfig, ScrollChainConfig};
use revm::{
context::{
result::{InvalidTransaction, ResultAndState},
Expand Down Expand Up @@ -84,7 +85,7 @@ impl<E, R, Spec> ScrollBlockExecutor<E, R, Spec>
where
E: EvmExt,
R: ScrollReceiptBuilder,
Spec: ScrollHardforks + Clone,
Spec: ScrollHardforks + ChainConfig<Config = ScrollChainConfig> + Clone,
{
/// Creates a new [`ScrollBlockExecutor`].
pub fn new(evm: E, ctx: ScrollBlockExecutionCtx, spec: Spec, receipt_builder: R) -> Self {
Expand All @@ -110,7 +111,7 @@ where
+ FromTxWithCompressionInfo<R::Transaction>,
>,
R: ScrollReceiptBuilder<Transaction: Transaction + Encodable2718, Receipt: TxReceipt>,
Spec: ScrollHardforks,
Spec: ScrollHardforks + ChainConfig<Config = ScrollChainConfig>,
{
/// Executes all transactions in a block, applying pre and post execution changes. The provided
/// transaction compression infos are expected to be in the same order as the
Expand Down Expand Up @@ -147,7 +148,7 @@ where
Tx: FromRecoveredTx<R::Transaction> + FromTxWithEncoded<R::Transaction>,
>,
R: ScrollReceiptBuilder<Transaction: Transaction + Encodable2718, Receipt: TxReceipt>,
Spec: ScrollHardforks,
Spec: ScrollHardforks + ChainConfig<Config = ScrollChainConfig>,
{
type Transaction = R::Transaction;
type Receipt = R::Receipt;
Expand Down Expand Up @@ -269,6 +270,7 @@ where
// disable the base fee and nonce checks for l1 messages.
self.evm.with_base_fee_check(!is_l1_message);
self.evm.with_nonce_check(!is_l1_message);
self.evm.with_l1_data_fee_buffer_check(chain_spec.chain_config().l1_data_fee_buffer_check);

// execute and return the result.
self.evm.transact(&tx).map_err(move |err| BlockExecutionError::evm(err, hash))
Expand Down Expand Up @@ -334,6 +336,8 @@ pub trait EvmExt: Evm {
fn with_base_fee_check(&mut self, enabled: bool);
/// Sets whether the evm should enable or disable the nonce checks.
fn with_nonce_check(&mut self, enabled: bool);
/// Sets whether the evm should enable or disable the l1 data fee buffer checks.
fn with_l1_data_fee_buffer_check(&mut self, enabled: bool);
/// Returns the l1 fee for the transaction.
fn l1_fee(&self) -> Option<U256>;
}
Expand All @@ -352,6 +356,10 @@ where
self.ctx_mut().cfg.disable_nonce_check = !enabled;
}

fn with_l1_data_fee_buffer_check(&mut self, enabled: bool) {
self.ctx_mut().cfg.require_l1_data_fee_buffer = enabled;
}

fn l1_fee(&self) -> Option<U256> {
let l1_block_info = &self.ctx().chain;
let transaction_rlp_bytes = self.ctx().tx.rlp_bytes.as_ref()?;
Expand All @@ -368,8 +376,7 @@ where

/// Scroll block executor factory.
#[derive(Debug, Clone, Default, Copy)]
pub struct ScrollBlockExecutorFactory<R, Spec = ScrollHardfork, P = ScrollDefaultPrecompilesFactory>
{
pub struct ScrollBlockExecutorFactory<R, Spec, P = ScrollDefaultPrecompilesFactory> {
/// Receipt builder.
receipt_builder: R,
/// Chain specification.
Expand Down Expand Up @@ -404,7 +411,7 @@ impl<R, Spec, P> ScrollBlockExecutorFactory<R, Spec, P> {
impl<R, Spec, P> BlockExecutorFactory for ScrollBlockExecutorFactory<R, Spec, P>
where
R: ScrollReceiptBuilder<Transaction: Transaction + Encodable2718, Receipt: TxReceipt>,
Spec: ScrollHardforks,
Spec: ScrollHardforks + ChainConfig<Config = ScrollChainConfig> + Clone,
P: ScrollPrecompilesFactory,
ScrollTransactionIntoTxEnv<TxEnv>:
FromRecoveredTx<R::Transaction> + FromTxWithEncoded<R::Transaction>,
Expand All @@ -428,6 +435,6 @@ where
DB: Database + 'a,
I: Inspector<<Self::EvmFactory as EvmFactory>::Context<&'a mut State<DB>>> + 'a,
{
ScrollBlockExecutor::new(evm, ctx, &self.spec, &self.receipt_builder)
ScrollBlockExecutor::new(evm, ctx, self.spec.clone(), &self.receipt_builder)
}
}
7 changes: 7 additions & 0 deletions crates/scroll/chainspec/src/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ pub struct ScrollChainConfig {
/// The L1 configuration.
/// This field encapsulates specific settings and parameters required for L1
pub l1_config: L1Config,
/// Whether the buffer check for L1 data fee is enabled.
pub l1_data_fee_buffer_check: bool,
}

impl ScrollChainConfig {
Expand All @@ -141,6 +143,7 @@ impl ScrollChainConfig {
fee_vault_address: Some(SCROLL_FEE_VAULT_ADDRESS),
max_tx_payload_bytes_per_block: MAX_TX_PAYLOAD_BYTES_PER_BLOCK,
l1_config: SCROLL_MAINNET_L1_CONFIG,
l1_data_fee_buffer_check: false,
}
}

Expand All @@ -150,6 +153,7 @@ impl ScrollChainConfig {
fee_vault_address: Some(SCROLL_FEE_VAULT_ADDRESS),
max_tx_payload_bytes_per_block: MAX_TX_PAYLOAD_BYTES_PER_BLOCK,
l1_config: SCROLL_SEPOLIA_L1_CONFIG,
l1_data_fee_buffer_check: false,
}
}

Expand All @@ -159,6 +163,7 @@ impl ScrollChainConfig {
fee_vault_address: Some(SCROLL_FEE_VAULT_ADDRESS),
max_tx_payload_bytes_per_block: MAX_TX_PAYLOAD_BYTES_PER_BLOCK,
l1_config: SCROLL_DEV_L1_CONFIG,
l1_data_fee_buffer_check: false,
}
}
}
Expand Down Expand Up @@ -232,6 +237,7 @@ mod tests {
"scroll": {
"feeVaultAddress": "0x5300000000000000000000000000000000000005",
"maxTxPayloadBytesPerBlock": 122880,
"l1DataFeeBufferCheck": false,
"l1Config": {
"l1ChainId": 1,
"l1MessageQueueAddress": "0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B",
Expand Down Expand Up @@ -273,6 +279,7 @@ mod tests {
scroll_chain_address: address!("a13BAF47339d63B743e7Da8741db5456DAc1E556"),
num_l1_messages_per_block: 10,
},
l1_data_fee_buffer_check: false,
},
};
assert_eq!(chain_info, expected);
Expand Down
3 changes: 3 additions & 0 deletions crates/scroll/chainspec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,7 @@ mod tests {
"scroll": {
"feeVaultAddress": "0x5300000000000000000000000000000000000005",
"maxTxPayloadBytesPerBlock": 122880,
"l1DataFeeBufferCheck": false,
"l1Config": {
"l1ChainId": 1,
"l1MessageQueueAddress": "0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B",
Expand Down Expand Up @@ -798,6 +799,7 @@ mod tests {
&serde_json::json!({
"feeVaultAddress": "0x5300000000000000000000000000000000000005",
"maxTxPayloadBytesPerBlock": 122880,
"l1DataFeeBufferCheck": false,
"l1Config": {
"l1ChainId": 1,
"l1MessageQueueAddress": "0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B",
Expand Down Expand Up @@ -864,6 +866,7 @@ mod tests {
serde_json::json!({
"feeVaultAddress": "0x5300000000000000000000000000000000000005",
"maxTxPayloadBytesPerBlock": 122880,
"l1DataFeeBufferCheck": false,
"l1Config": {
"l1ChainId": 1,
"l1MessageQueueAddress": "0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B",
Expand Down
14 changes: 10 additions & 4 deletions crates/scroll/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use alloc::sync::Arc;

use alloy_primitives::{Address, BlockNumber, BlockTimestamp};
use reth_primitives_traits::NodePrimitives;
use reth_scroll_chainspec::ScrollChainSpec;
use reth_scroll_chainspec::{ChainConfig, ScrollChainConfig, ScrollChainSpec};
use reth_scroll_primitives::ScrollPrimitives;
use revm_scroll::ScrollSpecId;
pub use scroll_alloy_evm::{
Expand All @@ -56,7 +56,9 @@ pub struct ScrollEvmConfig<
_pd: core::marker::PhantomData<N>,
}

impl<ChainSpec: ScrollHardforks> ScrollEvmConfig<ChainSpec> {
impl<ChainSpec: ScrollHardforks + ChainConfig<Config = ScrollChainConfig>>
ScrollEvmConfig<ChainSpec>
{
/// Creates a new [`ScrollEvmConfig`] with the given chain spec for Scroll chains.
pub fn scroll(chain_spec: Arc<ChainSpec>) -> Self {
Self::new(chain_spec, ScrollRethReceiptBuilder::default())
Expand All @@ -75,8 +77,12 @@ impl<ChainSpec, N: NodePrimitives, R: Clone, P: Clone> Clone
}
}

impl<ChainSpec: ScrollHardforks, N: NodePrimitives, R, P: Default>
ScrollEvmConfig<ChainSpec, N, R, P>
impl<
ChainSpec: ScrollHardforks + ChainConfig<Config = ScrollChainConfig>,
N: NodePrimitives,
R,
P: Default,
> ScrollEvmConfig<ChainSpec, N, R, P>
{
/// Creates a new [`ScrollEvmConfig`] with the given chain spec.
pub fn new(chain_spec: Arc<ChainSpec>, receipt_builder: R) -> Self {
Expand Down
37 changes: 5 additions & 32 deletions crates/scroll/node/src/builder/pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,13 @@ use scroll_alloy_hardforks::ScrollHardforks;
pub struct ScrollPoolBuilder<T = reth_scroll_txpool::ScrollPooledTransaction> {
/// Enforced overrides that are applied to the pool config.
pub pool_config_overrides: PoolBuilderConfigOverrides,
/// Require L1 data fee buffer in balance check.
/// When enabled, validates balance >= `L2_cost` + 2*`L1_cost` but only charges `L2_cost` +
/// 1*`L1_cost`.
pub require_l1_data_fee_buffer: bool,
/// Marker for the pooled transaction type.
_pd: core::marker::PhantomData<T>,
}

impl<T> Default for ScrollPoolBuilder<T> {
fn default() -> Self {
Self {
pool_config_overrides: Default::default(),
require_l1_data_fee_buffer: false,
_pd: Default::default(),
}
Self { pool_config_overrides: Default::default(), _pd: Default::default() }
}
}

Expand All @@ -51,14 +43,6 @@ impl<T> ScrollPoolBuilder<T> {
self.pool_config_overrides = pool_config_overrides;
self
}

/// Sets the require L1 data fee buffer flag.
/// When enabled, validates balance >= `L2_cost` + 2*`L1_cost` but only charges `L2_cost` +
/// 1*`L1_cost`. This matches geth's block validation behavior.
pub const fn with_require_l1_data_fee_buffer(mut self, require: bool) -> Self {
self.require_l1_data_fee_buffer = require;
self
}
}

impl<Node, T> PoolBuilder<Node> for ScrollPoolBuilder<T>
Expand All @@ -73,7 +57,7 @@ where
type Pool = ScrollTransactionPool<Node::Provider, DiskFileBlobStore, T>;

async fn build_pool(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Pool> {
let Self { pool_config_overrides, require_l1_data_fee_buffer, .. } = self;
let Self { pool_config_overrides, .. } = self;
let data_dir = ctx.config().datadir();
let blob_store = DiskFileBlobStore::open(data_dir.blobstore(), Default::default())?;

Expand All @@ -96,7 +80,9 @@ where
// In --dev mode we can't require gas fees because we're unable to decode
// the L1 block info
.require_l1_data_gas_fee(!ctx.config().dev.dev)
.require_l1_data_fee_buffer(require_l1_data_fee_buffer)
.require_l1_data_fee_buffer(
ctx.chain_spec().chain_config().l1_data_fee_buffer_check,
)
});

let transaction_pool = reth_transaction_pool::Pool::new(
Expand Down Expand Up @@ -396,19 +382,6 @@ mod tests {
drop(manager);
}

#[test]
fn test_pool_builder_with_require_l1_data_fee_buffer() {
// Test that the builder method correctly sets the flag
let pool_builder = ScrollPoolBuilder::<ScrollPooledTransaction>::default();
assert!(!pool_builder.require_l1_data_fee_buffer);

let pool_builder = pool_builder.with_require_l1_data_fee_buffer(true);
assert!(pool_builder.require_l1_data_fee_buffer);

let pool_builder = pool_builder.with_require_l1_data_fee_buffer(false);
assert!(!pool_builder.require_l1_data_fee_buffer);
}

#[tokio::test]
async fn test_l1_data_fee_buffer_validation() {
// Test that the L1 data fee buffer feature correctly validates transactions:
Expand Down
Loading