From 887bfdde9baddbd8601855aef769450844181057 Mon Sep 17 00:00:00 2001 From: James Date: Tue, 4 Nov 2025 14:46:11 -0500 Subject: [PATCH 1/9] feat: alias addresses --- Cargo.toml | 91 ++++---- crates/block-processor/src/v1/processor.rs | 45 +++- crates/node/src/node.rs | 1 + crates/rpc/Cargo.toml | 5 +- crates/rpc/examples/filler.rs | 246 --------------------- crates/rpc/examples/order.rs | 90 -------- crates/rpc/src/ctx/signet.rs | 11 +- crates/rpc/src/receipts.rs | 2 +- 8 files changed, 96 insertions(+), 395 deletions(-) delete mode 100644 crates/rpc/examples/filler.rs delete mode 100644 crates/rpc/examples/order.rs diff --git a/Cargo.toml b/Cargo.toml index b8ab0d1..a9c0bfd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = ["crates/*"] resolver = "2" [workspace.package] -version = "0.11.4" +version = "0.12.4" edition = "2024" rust-version = "1.88" authors = ["init4"] @@ -34,34 +34,34 @@ debug = false incremental = false [workspace.dependencies] -signet-blobber = { version = "0.11", path = "crates/blobber" } -signet-block-processor = { version = "0.11", path = "crates/block-processor" } -signet-db = { version = "0.11", path = "crates/db" } -signet-genesis = { version = "0.11", path = "crates/genesis" } -signet-node = { version = "0.11", path = "crates/node" } -signet-node-config = { version = "0.11", path = "crates/node-config" } -signet-node-tests = { version = "0.11", path = "crates/node-tests" } -signet-node-types = { version = "0.11", path = "crates/node-types" } -signet-rpc = { version = "0.11", path = "crates/rpc" } - +signet-blobber = { version = "0.12", path = "crates/blobber" } +signet-block-processor = { version = "0.12", path = "crates/block-processor" } +signet-db = { version = "0.12", path = "crates/db" } +signet-genesis = { version = "0.12", path = "crates/genesis" } +signet-node = { version = "0.12", path = "crates/node" } +signet-node-config = { version = "0.12", path = "crates/node-config" } +signet-node-tests = { version = "0.12", path = "crates/node-tests" } +signet-node-types = { version = "0.12", path = "crates/node-types" } +signet-rpc = { version = "0.12", path = "crates/rpc" } init4-bin-base = { version = "0.13.1", features = ["alloy"] } -signet-bundle = "0.11.1" -signet-constants = "0.11.1" -signet-evm = "0.11.1" -signet-extract = "0.11.1" -signet-test-utils = "0.11.1" -signet-tx-cache = "0.11.1" -signet-types = "0.11.1" -signet-zenith = "0.11.1" -signet-journal = "0.11.1" +signet-bundle = "0.12" +signet-constants = "0.12" +signet-evm = "0.12" +signet-extract = "0.12" +signet-test-utils = "0.12" +signet-tx-cache = "0.12" +signet-types = "0.12" +signet-zenith = "0.12" +signet-journal = "0.12" # ajj ajj = { version = "0.3.4" } # trevm trevm = { version = "0.29.0", features = ["full_env_cfg"] } +revm-inspectors = "0.30.0" # should be 1 more than trevm version, usually # Alloy periphery crates alloy = { version = "1.0.35", features = [ @@ -74,22 +74,22 @@ alloy = { version = "1.0.35", features = [ alloy-contract = { version = "1.0.35", features = ["pubsub"] } # Reth -reth = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" } -reth-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" } -reth-chainspec = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" } -reth-db = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" } -reth-db-common = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" } -reth-eth-wire-types = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" } -reth-evm-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" } -reth-exex = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" } -reth-exex-test-utils = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" } -reth-network-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" } -reth-network-peers = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" } -reth-node-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" } -reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" } -reth-prune-types = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" } -reth-rpc-eth-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" } -reth-transaction-pool = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" } +reth = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } +reth-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } +reth-chainspec = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } +reth-db = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } +reth-db-common = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } +reth-eth-wire-types = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } +reth-evm-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } +reth-exex = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } +reth-exex-test-utils = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } +reth-network-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } +reth-network-peers = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } +reth-node-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } +reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } +reth-prune-types = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } +reth-rpc-eth-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } +reth-transaction-pool = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } # Foundry periphery foundry-blob-explorers = "0.17" @@ -127,14 +127,15 @@ uuid = "1.16.0" alloy-rlp = "0.3.11" tempfile = "3.17.0" -# [patch.crates-io] -# signet-bundle = { path = "../sdk/crates/bundle"} -# signet-constants = { path = "../sdk/crates/constants"} -# signet-evm = { path = "../sdk/crates/evm"} -# signet-extract = { path = "../sdk/crates/extract"} -# signet-test-utils = { path = "../sdk/crates/test-utils"} -# signet-tx-cache = { path = "../sdk/crates/tx-cache"} -# signet-types = { path = "../sdk/crates/types"} -# signet-zenith = { path = "../sdk/crates/zenith"} +[patch.crates-io] +signet-bundle = { path = "../sdk/crates/bundle"} +signet-constants = { path = "../sdk/crates/constants"} +signet-evm = { path = "../sdk/crates/evm"} +signet-extract = { path = "../sdk/crates/extract"} +signet-journal = { path = "../sdk/crates/journal"} +signet-test-utils = { path = "../sdk/crates/test-utils"} +signet-tx-cache = { path = "../sdk/crates/tx-cache"} +signet-types = { path = "../sdk/crates/types"} +signet-zenith = { path = "../sdk/crates/zenith"} # init4-bin-base = { path = "../shared" } diff --git a/crates/block-processor/src/v1/processor.rs b/crates/block-processor/src/v1/processor.rs index 9a5212f..60f7bec 100644 --- a/crates/block-processor/src/v1/processor.rs +++ b/crates/block-processor/src/v1/processor.rs @@ -1,10 +1,17 @@ use crate::{Chain, metrics}; -use alloy::{consensus::BlockHeader, primitives::B256}; +use alloy::{ + consensus::BlockHeader, + primitives::{Address, B256, map::HashSet}, +}; +use core::fmt; use eyre::ContextCompat; use init4_bin_base::utils::calc::SlotCalculator; use reth::{ primitives::EthPrimitives, - providers::{BlockNumReader, BlockReader, ExecutionOutcome, HeaderProvider, ProviderFactory}, + providers::{ + BlockNumReader, BlockReader, ExecutionOutcome, HeaderProvider, ProviderFactory, + StateProviderFactory, + }, revm::{database::StateProviderDatabase, db::StateBuilder}, }; use reth_chainspec::{ChainSpec, EthereumHardforks}; @@ -16,14 +23,12 @@ use signet_evm::{BlockResult, EvmNeedsCfg, SignetDriver}; use signet_extract::{Extractor, Extracts}; use signet_journal::HostJournal; use signet_node_types::{NodeTypesDbTrait, SignetNodeTypes}; -use std::collections::VecDeque; -use std::sync::Arc; +use std::{collections::VecDeque, sync::Arc}; use tracing::{Instrument, debug, error, info, info_span, instrument}; use trevm::revm::primitives::hardfork::SpecId; /// A block processor that listens to host chain commits and processes /// Signet blocks accordingly. -#[derive(Debug)] pub struct SignetBlockProcessor where Db: NodeTypesDbTrait, @@ -37,6 +42,9 @@ where /// A [`ProviderFactory`] instance to allow RU database access. ru_provider: ProviderFactory>, + /// A [`ProviderFactory`] instance to allow Host database access. + host_provider: Box, + /// The slot calculator. slot_calculator: SlotCalculator, @@ -44,6 +52,15 @@ where blob_cacher: CacheHandle, } +impl fmt::Debug for SignetBlockProcessor +where + Db: NodeTypesDbTrait, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SignetBlockProcessor").finish() + } +} + impl SignetBlockProcessor where Db: NodeTypesDbTrait, @@ -53,10 +70,11 @@ where constants: SignetSystemConstants, chain_spec: Arc, ru_provider: ProviderFactory>, + host_provider: Box, slot_calculator: SlotCalculator, blob_cacher: CacheHandle, ) -> Self { - Self { constants, chain_spec, ru_provider, slot_calculator, blob_cacher } + Self { constants, chain_spec, ru_provider, host_provider, slot_calculator, blob_cacher } } /// Get the active spec id at the given timestamp. @@ -92,6 +110,12 @@ where Ok(trevm) } + /// Check if the given address should be aliased. + fn should_alias(&self, host_height: u64, address: Address) -> eyre::Result { + let state = self.host_provider.history_by_block_number(host_height)?; + state.account_code(&address).map(|code| code.is_some()).map_err(Into::into) + } + /// Called when the host chain has committed a block or set of blocks. #[instrument(skip_all, fields(count = chain.len(), first = chain.first().number(), tip = chain.tip().number()))] pub async fn on_host_commit(&self, chain: &Chain) -> eyre::Result> @@ -239,8 +263,17 @@ where None => VecDeque::new(), }; + let mut to_alias: HashSet
= Default::default(); + for transact in block_extracts.transacts() { + let addr = transact.host_sender(); + if self.should_alias(host_height, addr)? { + to_alias.insert(addr); + } + } + let mut driver = SignetDriver::new( block_extracts, + to_alias, txns, parent_header.convert(), self.constants.clone(), diff --git a/crates/node/src/node.rs b/crates/node/src/node.rs index b1dbd8a..90c84bc 100644 --- a/crates/node/src/node.rs +++ b/crates/node/src/node.rs @@ -177,6 +177,7 @@ where constants.clone(), config.chain_spec().clone(), factory.clone(), + Box::new(ctx.provider().clone()), config.slot_calculator(), blob_cacher, ); diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index c06b86f..c579fa0 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -10,6 +10,7 @@ repository.workspace = true [dependencies] signet-node-types.workspace = true +signet-db.workspace = true signet-bundle.workspace = true signet-evm.workspace = true @@ -20,6 +21,8 @@ ajj.workspace = true trevm.workspace = true alloy.workspace = true +revm-inspectors.workspace = true + reth.workspace = true reth-chainspec.workspace = true reth-db.workspace = true @@ -42,8 +45,6 @@ tracing.workspace = true serde_json.workspace = true futures-util = "0.3.31" itertools.workspace = true -revm-inspectors = "0.30.0" -signet-db.workspace = true [dev-dependencies] signet-zenith.workspace = true diff --git a/crates/rpc/examples/filler.rs b/crates/rpc/examples/filler.rs deleted file mode 100644 index b1d9c6e..0000000 --- a/crates/rpc/examples/filler.rs +++ /dev/null @@ -1,246 +0,0 @@ -use alloy::{ - eips::Encodable2718, - network::{Ethereum, EthereumWallet, TransactionBuilder}, - primitives::Bytes, - providers::{ - Identity, Provider as _, RootProvider, SendableTx, - fillers::{ - BlobGasFiller, ChainIdFiller, FillProvider, GasFiller, JoinFill, NonceFiller, - WalletFiller, - }, - }, - rpc::types::{TransactionRequest, mev::EthSendBundle}, - signers::Signer, -}; -use eyre::{Error, eyre}; -use signet_bundle::SignetEthBundle; -use signet_constants::SignetConstants; -use signet_tx_cache::{client::TxCache, types::TxCacheSendBundleResponse}; -use signet_types::{AggregateOrders, SignedFill, SignedOrder, UnsignedFill}; -use std::{collections::HashMap, slice::from_ref}; - -/// Multiplier for converting gwei to wei. -const GWEI_TO_WEI: u64 = 1_000_000_000; - -/// Type alias for the provider used to build and submit transactions to the rollup and host. -type Provider = FillProvider< - JoinFill< - JoinFill< - Identity, - JoinFill>>, - >, - WalletFiller, - >, - RootProvider, - Ethereum, ->; - -/// Example code demonstrating API usage and patterns for Signet Fillers. -#[derive(Debug)] -pub struct Filler { - /// The signer to use for signing transactions. - signer: S, - /// The provider to use for building transactions on the Rollup. - ru_provider: Provider, - /// The transaction cache endpoint. - tx_cache: TxCache, - /// The system constants. - constants: SignetConstants, -} - -impl Filler -where - S: Signer, -{ - /// Create a new Filler with the given signer, provider, and transaction cache endpoint. - pub fn new( - signer: S, - ru_provider: Provider, - constants: SignetConstants, - ) -> Result { - Ok(Self { - signer, - ru_provider, - tx_cache: TxCache::new_from_string(constants.environment().transaction_cache())?, - constants, - }) - } - - /// Query the transaction cache to get all possible orders. - pub async fn get_orders(&self) -> Result, Error> { - self.tx_cache.get_orders().await - } - - /// Fills Orders individually, by submitting a separate Bundle for each Order. - /// - /// Filling Orders individually ensures that even if some Orders are not fillable, others may still mine; - /// however, it is less gas efficient. - /// - /// A nice feature of filling Orders individually is that Fillers could be less concerned - /// about carefully simulating Orders onchain before attempting to fill them. - /// As long as an Order is economically a "good deal" for the Filler, they can attempt to fill it - /// without simulating to check whether it has already been filled, because they can rely on Builder simulation. - /// Order `initiate` transactions will revert if the Order has already been filled, - /// in which case the entire Bundle would simply be discarded by the Builder. - pub async fn fill_individually(&self, orders: &[SignedOrder]) -> Result<(), Error> { - // submit one bundle per individual order - for order in orders { - self.fill(from_ref(order)).await?; - } - - Ok(()) - } - - /// Fills one or more Order(s) in a single, atomic Bundle. - /// - Signs Fill(s) for the Order(s) - /// - Constructs a Bundle of transactions to fill & initiate the Order(s) - /// - Sends the Bundle to the transaction cache to be mined by Builders - /// - /// If more than one Order is passed to this fn, - /// Filling them in aggregate means that Fills are batched and more gas efficient; - /// however, if a single Order cannot be filled, then the entire Bundle will not mine. - /// For example, using this strategy, if one Order is filled by another Filler first, then all other Orders will also not be filled. - /// - /// If a single Order is passed to this fn, - /// Filling Orders individually ensures that even if some Orders are not fillable, others may still mine; - /// however, it is less gas efficient. - pub async fn fill(&self, orders: &[SignedOrder]) -> Result { - // if orders is empty, error out - if orders.is_empty() { - eyre::bail!("no orders to fill") - } - - // sign a SignedFill for the orders - let mut signed_fills = self.sign_fills(orders).await?; - - // get the transaction requests for the rollup - let tx_requests = self.rollup_txn_requests(&signed_fills, orders).await?; - - // sign & encode the transactions for the Bundle - let txs = self.sign_and_encode_txns(tx_requests).await?; - - // get the aggregated host fill for the Bundle, if any - let host_fills = signed_fills.remove(&self.constants.host().chain_id()); - - // set the Bundle to only be valid if mined in the next rollup block - let block_number = self.ru_provider.get_block_number().await? + 1; - - // construct a Bundle containing the Rollup transactions and the Host fill (if any) - let bundle = SignetEthBundle { - host_fills, - bundle: EthSendBundle { - txs, - reverting_tx_hashes: vec![], // generally, if the Order initiations revert, then fills should not be submitted - block_number, - min_timestamp: None, // sufficiently covered by pinning to next block number - max_timestamp: None, // sufficiently covered by pinning to next block number - replacement_uuid: None, // optional if implementing strategies that replace or cancel bundles - ..Default::default() // all other options are not used. - }, - host_txs: vec![], - }; - - // submit the Bundle to the transaction cache - self.tx_cache.forward_bundle(bundle).await - } - - /// Aggregate the given orders into a SignedFill, sign it, and - /// return a HashMap of SignedFills for each destination chain. - /// - /// This is the simplest, minimally viable way to turn a set of SignedOrders into a single Aggregated Fill on each chain; - /// Fillers may wish to implement more complex setups. - /// - /// For example, if utilizing different signers for each chain, they may use `UnsignedFill.sign_for(chain_id)` instead of `sign()`. - /// - /// If filling multiple Orders, they may wish to utilize one Order's Outputs to provide another Order's rollup Inputs. - /// In this case, the Filler would wish to split up the Fills for each Order, - /// rather than signing a single, aggregate a Fill for each chain, as is done here. - async fn sign_fills(&self, orders: &[SignedOrder]) -> Result, Error> { - // create an AggregateOrder from the SignedOrders they want to fill - let agg: AggregateOrders = orders.iter().collect(); - // produce an UnsignedFill from the AggregateOrder - let mut unsigned_fill = UnsignedFill::from(&agg); - // populate the Order contract addresses for each chain - for chain_id in agg.target_chain_ids() { - unsigned_fill = unsigned_fill.with_chain( - chain_id, - self.constants - .system() - .orders_for(chain_id) - .ok_or(eyre!("invalid target chain id {}", chain_id))?, - ); - } - // sign the UnsignedFill, producing a SignedFill for each target chain - Ok(unsigned_fill.sign(&self.signer).await?) - } - - /// Construct a set of transaction requests to be submitted on the rollup. - /// - /// Perform a single, aggregate Fill upfront, then Initiate each Order. - /// Transaction requests look like [`fill_aggregate`, `initiate_1`, `initiate_2`]. - /// - /// This is the simplest, minimally viable way to get a set of Orders mined; - /// Fillers may wish to implement more complex strategies. - /// - /// For example, Fillers might utilize one Order's Inputs to fill subsequent Orders' Outputs. - /// In this case, the rollup transactions should look like [`fill_1`, `inititate_1`, `fill_2`, `initiate_2`]. - async fn rollup_txn_requests( - &self, - signed_fills: &HashMap, - orders: &[SignedOrder], - ) -> Result, Error> { - // construct the transactions to be submitted to the Rollup - let mut tx_requests = Vec::new(); - - // first, if there is a SignedFill for the Rollup, add a transaction to submit the fill - // Note that `fill` transactions MUST be mined *before* the corresponding Order(s) `initiate` transactions in order to cound - // Host `fill` transactions are always considered to be mined "before" the rollup block is processed, - // but Rollup `fill` transactions MUST take care to be ordered before the Orders are `initiate`d - if let Some(rollup_fill) = signed_fills.get(&self.constants.rollup().chain_id()) { - // add the fill tx to the rollup txns - let ru_fill_tx = rollup_fill.to_fill_tx(self.constants.rollup().orders()); - tx_requests.push(ru_fill_tx); - } - - // next, add a transaction to initiate each SignedOrder - for signed_order in orders { - // add the initiate tx to the rollup txns - let ru_initiate_tx = signed_order - .to_initiate_tx(self.signer.address(), self.constants.rollup().orders()); - tx_requests.push(ru_initiate_tx); - } - - Ok(tx_requests) - } - - /// Given an ordered set of Transaction Requests, - /// Sign them and encode them for inclusion in a Bundle. - pub async fn sign_and_encode_txns( - &self, - tx_requests: Vec, - ) -> Result, Error> { - let mut encoded_txs: Vec = Vec::new(); - for mut tx in tx_requests { - // fill out the transaction fields - tx = tx - .with_from(self.signer.address()) - .with_gas_limit(1_000_000) - .with_max_priority_fee_per_gas((GWEI_TO_WEI * 16) as u128); - - // sign the transaction - let SendableTx::Envelope(filled) = self.ru_provider.fill(tx).await? else { - eyre::bail!("Failed to fill transaction") - }; - - // encode it - let encoded = filled.encoded_2718(); - - // add to array - encoded_txs.push(Bytes::from(encoded)); - } - Ok(encoded_txs) - } -} - -/// Empty main to silence clippy. -fn main() {} diff --git a/crates/rpc/examples/order.rs b/crates/rpc/examples/order.rs deleted file mode 100644 index badb96a..0000000 --- a/crates/rpc/examples/order.rs +++ /dev/null @@ -1,90 +0,0 @@ -use alloy::{ - consensus::constants::GWEI_TO_WEI, - primitives::{U256, uint}, - signers::Signer, -}; -use chrono::Utc; -use eyre::Error; -use signet_constants::{NATIVE_TOKEN_ADDRESS, SignetConstants}; -use signet_tx_cache::client::TxCache; -use signet_types::UnsignedOrder; -use signet_zenith::RollupOrders::{Input, Order, Output}; - -const ONE_USDC: U256 = uint!(1_000_000_U256); - -/// Example code demonstrating API usage and patterns for signing an Order. -#[derive(Debug)] -pub struct SendOrder { - /// The signer to use for signing the order. - signer: S, - /// The transaction cache endpoint. - tx_cache: TxCache, - /// The system constants. - constants: SignetConstants, -} - -impl SendOrder -where - S: Signer, -{ - /// Create a new SendOrder instance. - pub fn new(signer: S, constants: SignetConstants) -> Result { - Ok(Self { - signer, - tx_cache: TxCache::new_from_string(constants.environment().transaction_cache())?, - constants, - }) - } - - /// Construct a simple example Order, sign it, and send it. - pub async fn run(&self) -> Result<(), Error> { - // get an example order - let order = self.example_order(); - - // sign and send the order - self.sign_and_send_order(order).await - } - - /// Sign an Order and send it to the transaction cache to be Filled. - pub async fn sign_and_send_order(&self, order: Order) -> Result<(), Error> { - // make an UnsignedOrder from the Order - let unsigned = UnsignedOrder::from(&order); - - // sign it - let signed = unsigned - .with_chain(self.constants.rollup().chain_id(), self.constants.rollup().orders()) - .sign(&self.signer) - .await?; - - // send the SignedOrder to the transaction cache - self.tx_cache.forward_order(signed).await - } - - /// Get an example Order which swaps 1 USDC on the rollup for 1 USDC on the host. - fn example_order(&self) -> Order { - // The native asset on the rollup has 18 decimals. - let amount = U256::from(GWEI_TO_WEI); - - // input is 1 USD on the rollup - let input = Input { token: NATIVE_TOKEN_ADDRESS, amount }; - - // output is 1 USDC on the host chain. - // NB: decimals are important! USDC has 6 decimals, while Signet's USD - // native asset has 18. - let output = Output { - token: self.constants.host().tokens().usdc(), - amount: ONE_USDC, - chainId: self.constants.host().chain_id() as u32, - recipient: self.signer.address(), - }; - - // deadline 60 seconds (or ~5 blocks) from now - let deadline = Utc::now().timestamp() + 60; - - // construct the order - Order { inputs: vec![input], outputs: vec![output], deadline: U256::from(deadline) } - } -} - -/// Empty main to silence clippy. -fn main() {} diff --git a/crates/rpc/src/ctx/signet.rs b/crates/rpc/src/ctx/signet.rs index 02661d0..1a06e91 100644 --- a/crates/rpc/src/ctx/signet.rs +++ b/crates/rpc/src/ctx/signet.rs @@ -298,11 +298,12 @@ where ) -> Result { let sig = tx.signature(); - let sender = if let Some(sender) = MagicSig::try_from_signature(sig).map(|s| s.sender()) { - sender - } else { - tx.recover_signer().map_err(|_| EthApiError::InvalidTransactionSignature)? - }; + let sender = + if let Some(sender) = MagicSig::try_from_signature(sig).map(|s| s.rollup_sender()) { + sender + } else { + tx.recover_signer().map_err(|_| EthApiError::InvalidTransactionSignature)? + }; let tx = Recovered::new_unchecked(tx, sender); diff --git a/crates/rpc/src/receipts.rs b/crates/rpc/src/receipts.rs index 69ccec5..6e45e95 100644 --- a/crates/rpc/src/receipts.rs +++ b/crates/rpc/src/receipts.rs @@ -22,7 +22,7 @@ pub fn build_signet_receipt( // in which case they'll use [`MagicSig`]s to preserve the sender with additional metadata. // Therefore, in case recovering the signer fails, we try to parse the signature as a magic signature. let from = MagicSig::try_from_signature(transaction.signature()) - .map(|magic_sig| magic_sig.sender()) + .map(|magic_sig| magic_sig.rollup_sender()) .or_else(|| transaction.recover_signer_unchecked().ok()) .ok_or_else(|| EthApiError::InvalidTransactionSignature)?; From d48ce804fa0d18cdd7b4070ef9b648f1438212e1 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 5 Nov 2025 10:42:27 -0500 Subject: [PATCH 2/9] feat: alias oracle --- crates/block-processor/src/alias.rs | 65 ++++++++++++++++++++++ crates/block-processor/src/lib.rs | 3 + crates/block-processor/src/v1/processor.rs | 21 +++---- crates/node/src/node.rs | 7 ++- 4 files changed, 84 insertions(+), 12 deletions(-) create mode 100644 crates/block-processor/src/alias.rs diff --git a/crates/block-processor/src/alias.rs b/crates/block-processor/src/alias.rs new file mode 100644 index 0000000..7d053d9 --- /dev/null +++ b/crates/block-processor/src/alias.rs @@ -0,0 +1,65 @@ +use alloy::{ + consensus::constants::KECCAK_EMPTY, + primitives::{Address, map::HashSet}, +}; +use eyre::OptionExt; +use reth::providers::{StateProvider, StateProviderFactory}; + +/// Simple trait to allow checking if an address should be aliased. +pub trait AliasOracle { + /// Returns true if the given address is an alias. + fn should_alias(&self, address: Address) -> eyre::Result; +} + +impl AliasOracle for Box { + fn should_alias(&self, address: Address) -> eyre::Result { + let Some(acct) = self.basic_account(&address)? else { return Ok(false) }; + let bch = match acct.bytecode_hash { + Some(hash) => hash, + None => return Ok(false), + }; + if bch == KECCAK_EMPTY { + return Ok(false); + } + let code = self + .bytecode_by_hash(&bch)? + .ok_or_eyre("code not found. This indicates a corrupted database")?; + + // Check for 7702 delegations. + if code.len() != 23 || !code.bytecode().starts_with(&[0xef, 0x01, 0x00]) { + return Ok(true); + } + Ok(false) + } +} + +impl AliasOracle for &HashSet
{ + fn should_alias(&self, address: Address) -> eyre::Result { + Ok(self.contains(&address)) + } +} + +/// Factory trait to create new [`AliasOracle`] instances. +pub trait AliasOracleFactory: Send + Sync + 'static { + /// The [`AliasOracle`] type. + type Oracle<'a>: AliasOracle; + + /// Create a new [`AliasOracle`]. + fn create(&self, block_height: u64) -> eyre::Result>; +} + +impl AliasOracleFactory for Box { + type Oracle<'a> = Box; + + fn create(&self, block_height: u64) -> eyre::Result> { + self.state_by_block_number_or_tag(block_height.into()).map_err(Into::into) + } +} + +impl AliasOracleFactory for HashSet
{ + type Oracle<'a> = &'a HashSet
; + + fn create(&self, _block_height: u64) -> eyre::Result> { + Ok(self) + } +} diff --git a/crates/block-processor/src/lib.rs b/crates/block-processor/src/lib.rs index 818077d..87341a2 100644 --- a/crates/block-processor/src/lib.rs +++ b/crates/block-processor/src/lib.rs @@ -13,6 +13,9 @@ pub(crate) mod metrics; +mod alias; +pub use alias::{AliasOracle, AliasOracleFactory}; + mod v1; pub use v1::SignetBlockProcessor as SignetBlockProcessorV1; diff --git a/crates/block-processor/src/v1/processor.rs b/crates/block-processor/src/v1/processor.rs index 60f7bec..e3a8118 100644 --- a/crates/block-processor/src/v1/processor.rs +++ b/crates/block-processor/src/v1/processor.rs @@ -1,4 +1,4 @@ -use crate::{Chain, metrics}; +use crate::{AliasOracle, AliasOracleFactory, Chain, metrics}; use alloy::{ consensus::BlockHeader, primitives::{Address, B256, map::HashSet}, @@ -29,7 +29,7 @@ use trevm::revm::primitives::hardfork::SpecId; /// A block processor that listens to host chain commits and processes /// Signet blocks accordingly. -pub struct SignetBlockProcessor +pub struct SignetBlockProcessor> where Db: NodeTypesDbTrait, { @@ -43,7 +43,7 @@ where ru_provider: ProviderFactory>, /// A [`ProviderFactory`] instance to allow Host database access. - host_provider: Box, + alias_oracle: Alias, /// The slot calculator. slot_calculator: SlotCalculator, @@ -61,20 +61,21 @@ where } } -impl SignetBlockProcessor +impl SignetBlockProcessor where Db: NodeTypesDbTrait, + Alias: AliasOracleFactory, { /// Create a new [`SignetBlockProcessor`]. pub const fn new( constants: SignetSystemConstants, chain_spec: Arc, ru_provider: ProviderFactory>, - host_provider: Box, + alias_oracle: Alias, slot_calculator: SlotCalculator, blob_cacher: CacheHandle, ) -> Self { - Self { constants, chain_spec, ru_provider, host_provider, slot_calculator, blob_cacher } + Self { constants, chain_spec, ru_provider, alias_oracle, slot_calculator, blob_cacher } } /// Get the active spec id at the given timestamp. @@ -111,9 +112,8 @@ where } /// Check if the given address should be aliased. - fn should_alias(&self, host_height: u64, address: Address) -> eyre::Result { - let state = self.host_provider.history_by_block_number(host_height)?; - state.account_code(&address).map(|code| code.is_some()).map_err(Into::into) + fn should_alias(&self, address: Address, host_height: u64) -> eyre::Result { + self.alias_oracle.create(host_height)?.should_alias(address) } /// Called when the host chain has committed a block or set of blocks. @@ -263,10 +263,11 @@ where None => VecDeque::new(), }; + // Determine which addresses need to be aliased. let mut to_alias: HashSet
= Default::default(); for transact in block_extracts.transacts() { let addr = transact.host_sender(); - if self.should_alias(host_height, addr)? { + if !to_alias.contains(&addr) && self.should_alias(addr, host_height)? { to_alias.insert(addr); } } diff --git a/crates/node/src/node.rs b/crates/node/src/node.rs index 90c84bc..5f89c9c 100644 --- a/crates/node/src/node.rs +++ b/crates/node/src/node.rs @@ -11,7 +11,8 @@ use reth::{ providers::{ BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, CanonChainTracker, CanonStateNotification, CanonStateNotifications, CanonStateSubscriptions, HeaderProvider, - NodePrimitivesProvider, ProviderFactory, providers::BlockchainProvider, + NodePrimitivesProvider, ProviderFactory, StateProviderFactory, + providers::BlockchainProvider, }, rpc::types::engine::ForkchoiceState, }; @@ -173,11 +174,13 @@ where .wrap_err("failed to create blob cacher")? .spawn(); + let bdsp: Box = Box::new(ctx.provider().clone()); + let processor = SignetBlockProcessorV1::new( constants.clone(), config.chain_spec().clone(), factory.clone(), - Box::new(ctx.provider().clone()), + bdsp, config.slot_calculator(), blob_cacher, ); From 30819158f4f7a7743928073cec75071305e09697 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 5 Nov 2025 11:09:31 -0500 Subject: [PATCH 3/9] chore: bump to 0.13 off aliasing branch --- Cargo.toml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a9c0bfd..518ea66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,15 +46,15 @@ signet-rpc = { version = "0.12", path = "crates/rpc" } init4-bin-base = { version = "0.13.1", features = ["alloy"] } -signet-bundle = "0.12" -signet-constants = "0.12" -signet-evm = "0.12" -signet-extract = "0.12" -signet-test-utils = "0.12" -signet-tx-cache = "0.12" -signet-types = "0.12" -signet-zenith = "0.12" -signet-journal = "0.12" +signet-bundle = "0.13" +signet-constants = "0.13" +signet-evm = "0.13" +signet-extract = "0.13" +signet-test-utils = "0.13" +signet-tx-cache = "0.13" +signet-types = "0.13" +signet-zenith = "0.13" +signet-journal = "0.13" # ajj ajj = { version = "0.3.4" } From c86e37db5cd33e6159d774e0c43ed4afd7ec797f Mon Sep 17 00:00:00 2001 From: James Date: Wed, 5 Nov 2025 11:28:40 -0500 Subject: [PATCH 4/9] fix: tests pass again --- crates/block-processor/src/alias.rs | 51 ++++++++++++++++++++++++----- crates/node-tests/src/context.rs | 33 ++++++++++++++++--- crates/node-tests/tests/db.rs | 11 +++++-- crates/node/src/node.rs | 21 ++++++------ crates/node/src/rpc.rs | 4 ++- 5 files changed, 94 insertions(+), 26 deletions(-) diff --git a/crates/block-processor/src/alias.rs b/crates/block-processor/src/alias.rs index 7d053d9..68206e8 100644 --- a/crates/block-processor/src/alias.rs +++ b/crates/block-processor/src/alias.rs @@ -4,6 +4,7 @@ use alloy::{ }; use eyre::OptionExt; use reth::providers::{StateProvider, StateProviderFactory}; +use std::sync::{Arc, Mutex}; /// Simple trait to allow checking if an address should be aliased. pub trait AliasOracle { @@ -33,33 +34,67 @@ impl AliasOracle for Box { } } -impl AliasOracle for &HashSet
{ +impl AliasOracle for HashSet
{ fn should_alias(&self, address: Address) -> eyre::Result { Ok(self.contains(&address)) } } /// Factory trait to create new [`AliasOracle`] instances. +/// +/// The default implementation on `Box` creates +/// [`AliasOracle`] instances backed by the state provider for a given block +/// height. It will error if that state provider cannot be obtained. +/// +/// This trait is primarily intended to allow injecting test implementations +/// of [`AliasOracle`] into the Signet Node for testing purposes. The test +/// implementation on [`HashSet
`] allows specifying a fixed set of +/// addresses to be aliased. pub trait AliasOracleFactory: Send + Sync + 'static { /// The [`AliasOracle`] type. - type Oracle<'a>: AliasOracle; + type Oracle: AliasOracle; /// Create a new [`AliasOracle`]. - fn create(&self, block_height: u64) -> eyre::Result>; + fn create(&self, block_height: u64) -> eyre::Result; } impl AliasOracleFactory for Box { - type Oracle<'a> = Box; + type Oracle = Box; - fn create(&self, block_height: u64) -> eyre::Result> { + fn create(&self, block_height: u64) -> eyre::Result { self.state_by_block_number_or_tag(block_height.into()).map_err(Into::into) } } +/// This implementation is primarily for testing purposes. impl AliasOracleFactory for HashSet
{ - type Oracle<'a> = &'a HashSet
; + type Oracle = HashSet
; - fn create(&self, _block_height: u64) -> eyre::Result> { - Ok(self) + fn create(&self, _block_height: u64) -> eyre::Result { + Ok(self.clone()) + } +} + +impl AliasOracleFactory for Mutex +where + T: AliasOracleFactory, +{ + type Oracle = T::Oracle; + + fn create(&self, block_height: u64) -> eyre::Result { + let guard = + self.lock().map_err(|_| eyre::eyre!("failed to lock AliasOracleFactory mutex"))?; + guard.create(block_height) + } +} + +impl AliasOracleFactory for Arc +where + T: AliasOracleFactory, +{ + type Oracle = T::Oracle; + + fn create(&self, block_height: u64) -> eyre::Result { + self.as_ref().create(block_height) } } diff --git a/crates/node-tests/src/context.rs b/crates/node-tests/src/context.rs index 921bfd4..541357e 100644 --- a/crates/node-tests/src/context.rs +++ b/crates/node-tests/src/context.rs @@ -8,7 +8,7 @@ use alloy::{ consensus::{BlockHeader, TxEnvelope, constants::ETH_TO_WEI}, genesis::{Genesis, GenesisAccount}, network::{Ethereum, EthereumWallet, TransactionBuilder as _}, - primitives::{Address, I256, Sign, U256, keccak256}, + primitives::{Address, I256, Sign, U256, keccak256, map::HashSet}, providers::{ Provider as _, ProviderBuilder, SendableTx, fillers::{BlobGasFiller, SimpleNonceManager}, @@ -31,7 +31,7 @@ use signet_test_utils::contracts::counter::COUNTER_DEPLOY_CODE; use signet_types::constants::{HostPermitted, RollupPermitted, SignetSystemConstants}; use signet_zenith::{HostOrders::OrdersInstance, RollupPassage::RollupPassageInstance}; use std::sync::{ - Arc, + Arc, Mutex, atomic::{AtomicU64, Ordering}, }; use tokio::{sync::watch, task::JoinHandle}; @@ -74,7 +74,10 @@ pub struct SignetTestContext { /// The current host block height pub height: AtomicU64, - /// Test addreses, copied from [`signet_types::test_utils::TEST_USERS`] for + /// The alias oracle used by the Signet Node instance. + pub alias_oracle: Arc>>, + + /// Test addresses, copied from [`signet_types::test_utils::TEST_USERS`] for /// convenience pub addresses: [Address; 10], } @@ -99,9 +102,17 @@ impl SignetTestContext { let factory = create_test_provider_factory_with_chain_spec(chain_spec.clone()); + let alias_oracle: Arc>> = Arc::new(Mutex::new(HashSet::default())); + // instantiate Signet Node, booting rpc - let (node, mut node_status) = - SignetNode::new(ctx, cfg.clone(), factory.clone(), Default::default()).unwrap(); + let (node, mut node_status) = SignetNode::new( + ctx, + cfg.clone(), + factory.clone(), + Arc::clone(&alias_oracle), + Default::default(), + ) + .unwrap(); // Spawn the node, and wait for it to indicate RPC readiness. let node = tokio::spawn(node.start()); @@ -152,12 +163,24 @@ impl SignetTestContext { constants, height: AtomicU64::new(cfg.constants().unwrap().host_deploy_height()), + alias_oracle, addresses, }; (this, node) } + /// Set whether an address should be aliased. This will be propagated to + /// the running node. + pub fn set_should_alias(&self, address: Address, should_alias: bool) { + let mut guard = self.alias_oracle.lock().expect("failed to lock alias oracle mutex"); + if should_alias { + guard.insert(address); + } else { + guard.remove(&address); + } + } + /// Clone the Signet system constants pub fn constants(&self) -> SignetSystemConstants { self.constants.clone() diff --git a/crates/node-tests/tests/db.rs b/crates/node-tests/tests/db.rs index 0b26342..c83633e 100644 --- a/crates/node-tests/tests/db.rs +++ b/crates/node-tests/tests/db.rs @@ -1,4 +1,4 @@ -use alloy::primitives::hex; +use alloy::primitives::{Address, hex, map::HashSet}; use reth::providers::BlockReader; use serial_test::serial; use signet_node::SignetNode; @@ -17,7 +17,14 @@ async fn test_genesis() { assert_eq!(chain_spec.genesis().config.chain_id, consts.unwrap().ru_chain_id()); let factory = create_test_provider_factory_with_chain_spec(chain_spec.clone()); - let (_, _) = SignetNode::new(ctx, cfg.clone(), factory.clone(), Default::default()).unwrap(); + let (_, _) = SignetNode::<_, _, HashSet
>::new( + ctx, + cfg.clone(), + factory.clone(), + Default::default(), + Default::default(), + ) + .unwrap(); let genesis_block = factory.provider().unwrap().block_by_number(0).unwrap().unwrap(); diff --git a/crates/node/src/node.rs b/crates/node/src/node.rs index 5f89c9c..67934e7 100644 --- a/crates/node/src/node.rs +++ b/crates/node/src/node.rs @@ -22,7 +22,7 @@ use reth_db_common::init; use reth_exex::{ExExContext, ExExEvent, ExExHead, ExExNotificationsStream}; use reth_node_api::{FullNodeComponents, FullNodeTypes, NodeTypes}; use signet_blobber::BlobFetcher; -use signet_block_processor::SignetBlockProcessorV1; +use signet_block_processor::{AliasOracleFactory, SignetBlockProcessorV1}; use signet_db::{DbProviderExt, RuChain, RuWriter}; use signet_node_config::SignetNodeConfig; use signet_node_types::{NodeStatus, NodeTypesDbTrait, SignetNodeTypes}; @@ -42,7 +42,7 @@ type ExExNotification = reth_exex::ExExNotification>; type Chain = reth::providers::Chain>; /// Signet context and configuration. -pub struct SignetNode +pub struct SignetNode> where Host: FullNodeComponents, Host::Types: NodeTypes, @@ -72,13 +72,13 @@ where pub(crate) status: watch::Sender, /// The block processor - pub(crate) processor: SignetBlockProcessorV1, + pub(crate) processor: SignetBlockProcessorV1, /// A reqwest client, used by the blob fetch and the tx cache forwarder. pub(crate) client: reqwest::Client, } -impl fmt::Debug for SignetNode +impl fmt::Debug for SignetNode where Host: FullNodeComponents, Host::Types: NodeTypes, @@ -89,7 +89,7 @@ where } } -impl NodePrimitivesProvider for SignetNode +impl NodePrimitivesProvider for SignetNode where Host: FullNodeComponents, Host::Types: NodeTypes, @@ -98,22 +98,24 @@ where type Primitives = EthPrimitives; } -impl CanonStateSubscriptions for SignetNode +impl CanonStateSubscriptions for SignetNode where Host: FullNodeComponents, Host::Types: NodeTypes, Db: NodeTypesDbTrait, + AliasOracle: AliasOracleFactory, { fn subscribe_to_canonical_state(&self) -> CanonStateNotifications { self.bp.subscribe_to_canonical_state() } } -impl SignetNode +impl SignetNode where Host: FullNodeComponents, Host::Types: NodeTypes, Db: NodeTypesDbTrait, + AliasOracle: AliasOracleFactory, { /// Create a new Signet instance. /// @@ -124,6 +126,7 @@ where ctx: ExExContext, config: SignetNodeConfig, factory: ProviderFactory>, + alias_oracle: AliasOracle, client: reqwest::Client, ) -> eyre::Result<(Self, tokio::sync::watch::Receiver)> { let constants = @@ -174,13 +177,11 @@ where .wrap_err("failed to create blob cacher")? .spawn(); - let bdsp: Box = Box::new(ctx.provider().clone()); - let processor = SignetBlockProcessorV1::new( constants.clone(), config.chain_spec().clone(), factory.clone(), - bdsp, + alias_oracle, config.slot_calculator(), blob_cacher, ); diff --git a/crates/node/src/rpc.rs b/crates/node/src/rpc.rs index 0536bfb..c69e7b5 100644 --- a/crates/node/src/rpc.rs +++ b/crates/node/src/rpc.rs @@ -1,16 +1,18 @@ use crate::SignetNode; use reth::{primitives::EthPrimitives, rpc::builder::config::RethRpcServerConfig}; use reth_node_api::{FullNodeComponents, NodeTypes}; +use signet_block_processor::AliasOracleFactory; use signet_node_types::NodeTypesDbTrait; use signet_rpc::{RpcCtx, RpcServerGuard, ServeConfig}; use signet_tx_cache::client::TxCache; use tracing::info; -impl SignetNode +impl SignetNode where Host: FullNodeComponents, Host::Types: NodeTypes, Db: NodeTypesDbTrait, + AliasOracle: AliasOracleFactory, { /// Start the RPC server. pub async fn start_rpc(&mut self) -> eyre::Result<()> { From a588cb15c3e551359abdc854e603d86cc136fc86 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 5 Nov 2025 11:50:46 -0500 Subject: [PATCH 5/9] chore: remove state provider height --- crates/block-processor/src/alias.rs | 16 ++++++++-------- crates/block-processor/src/v1/processor.rs | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/block-processor/src/alias.rs b/crates/block-processor/src/alias.rs index 68206e8..908b64d 100644 --- a/crates/block-processor/src/alias.rs +++ b/crates/block-processor/src/alias.rs @@ -55,14 +55,14 @@ pub trait AliasOracleFactory: Send + Sync + 'static { type Oracle: AliasOracle; /// Create a new [`AliasOracle`]. - fn create(&self, block_height: u64) -> eyre::Result; + fn create(&self) -> eyre::Result; } impl AliasOracleFactory for Box { type Oracle = Box; - fn create(&self, block_height: u64) -> eyre::Result { - self.state_by_block_number_or_tag(block_height.into()).map_err(Into::into) + fn create(&self) -> eyre::Result { + self.state_by_block_number_or_tag(alloy::eips::BlockNumberOrTag::Latest).map_err(Into::into) } } @@ -70,7 +70,7 @@ impl AliasOracleFactory for Box { impl AliasOracleFactory for HashSet
{ type Oracle = HashSet
; - fn create(&self, _block_height: u64) -> eyre::Result { + fn create(&self) -> eyre::Result { Ok(self.clone()) } } @@ -81,10 +81,10 @@ where { type Oracle = T::Oracle; - fn create(&self, block_height: u64) -> eyre::Result { + fn create(&self) -> eyre::Result { let guard = self.lock().map_err(|_| eyre::eyre!("failed to lock AliasOracleFactory mutex"))?; - guard.create(block_height) + guard.create() } } @@ -94,7 +94,7 @@ where { type Oracle = T::Oracle; - fn create(&self, block_height: u64) -> eyre::Result { - self.as_ref().create(block_height) + fn create(&self) -> eyre::Result { + self.as_ref().create() } } diff --git a/crates/block-processor/src/v1/processor.rs b/crates/block-processor/src/v1/processor.rs index e3a8118..fd5aa30 100644 --- a/crates/block-processor/src/v1/processor.rs +++ b/crates/block-processor/src/v1/processor.rs @@ -112,8 +112,8 @@ where } /// Check if the given address should be aliased. - fn should_alias(&self, address: Address, host_height: u64) -> eyre::Result { - self.alias_oracle.create(host_height)?.should_alias(address) + fn should_alias(&self, address: Address) -> eyre::Result { + self.alias_oracle.create()?.should_alias(address) } /// Called when the host chain has committed a block or set of blocks. @@ -267,7 +267,7 @@ where let mut to_alias: HashSet
= Default::default(); for transact in block_extracts.transacts() { let addr = transact.host_sender(); - if !to_alias.contains(&addr) && self.should_alias(addr, host_height)? { + if !to_alias.contains(&addr) && self.should_alias(addr)? { to_alias.insert(addr); } } From 8e96f3826c5e6bedb90aa0955747d8ce403a8741 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 5 Nov 2025 12:07:29 -0500 Subject: [PATCH 6/9] chore: remove block height arg and add test --- Cargo.toml | 88 +++++++++---------- crates/block-processor/src/alias.rs | 24 +++-- crates/node-tests/src/context.rs | 4 +- crates/node-tests/src/lib.rs | 6 +- crates/node-tests/src/rpc.rs | 2 +- .../node-tests/src/{aliases.rs => types.rs} | 0 crates/node-tests/tests/host_events.rs | 50 ++++++++--- crates/node-tests/tests/orders.rs | 5 +- crates/node-tests/tests/rpc.rs | 2 +- crates/node-tests/tests/rpc_debug.rs | 2 +- crates/node-tests/tests/submit-tx.rs | 4 +- 11 files changed, 115 insertions(+), 72 deletions(-) rename crates/node-tests/src/{aliases.rs => types.rs} (100%) diff --git a/Cargo.toml b/Cargo.toml index 518ea66..77b999d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = ["crates/*"] resolver = "2" [workspace.package] -version = "0.12.4" +version = "0.14.0" edition = "2024" rust-version = "1.88" authors = ["init4"] @@ -34,27 +34,27 @@ debug = false incremental = false [workspace.dependencies] -signet-blobber = { version = "0.12", path = "crates/blobber" } -signet-block-processor = { version = "0.12", path = "crates/block-processor" } -signet-db = { version = "0.12", path = "crates/db" } -signet-genesis = { version = "0.12", path = "crates/genesis" } -signet-node = { version = "0.12", path = "crates/node" } -signet-node-config = { version = "0.12", path = "crates/node-config" } -signet-node-tests = { version = "0.12", path = "crates/node-tests" } -signet-node-types = { version = "0.12", path = "crates/node-types" } -signet-rpc = { version = "0.12", path = "crates/rpc" } +signet-blobber = { version = "0.14", path = "crates/blobber" } +signet-block-processor = { version = "0.14", path = "crates/block-processor" } +signet-db = { version = "0.14", path = "crates/db" } +signet-genesis = { version = "0.14", path = "crates/genesis" } +signet-node = { version = "0.14", path = "crates/node" } +signet-node-config = { version = "0.14", path = "crates/node-config" } +signet-node-tests = { version = "0.14", path = "crates/node-tests" } +signet-node-types = { version = "0.14", path = "crates/node-types" } +signet-rpc = { version = "0.14", path = "crates/rpc" } init4-bin-base = { version = "0.13.1", features = ["alloy"] } -signet-bundle = "0.13" -signet-constants = "0.13" -signet-evm = "0.13" -signet-extract = "0.13" -signet-test-utils = "0.13" -signet-tx-cache = "0.13" -signet-types = "0.13" -signet-zenith = "0.13" -signet-journal = "0.13" +signet-bundle = "0.14" +signet-constants = "0.14" +signet-evm = "0.14" +signet-extract = "0.14" +signet-test-utils = "0.14" +signet-tx-cache = "0.14" +signet-types = "0.14" +signet-zenith = "0.14" +signet-journal = "0.14" # ajj ajj = { version = "0.3.4" } @@ -74,22 +74,22 @@ alloy = { version = "1.0.35", features = [ alloy-contract = { version = "1.0.35", features = ["pubsub"] } # Reth -reth = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } -reth-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } -reth-chainspec = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } -reth-db = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } -reth-db-common = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } -reth-eth-wire-types = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } -reth-evm-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } -reth-exex = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } -reth-exex-test-utils = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } -reth-network-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } -reth-network-peers = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } -reth-node-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } -reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } -reth-prune-types = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } -reth-rpc-eth-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } -reth-transaction-pool = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.3" } +reth = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" } +reth-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" } +reth-chainspec = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" } +reth-db = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" } +reth-db-common = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" } +reth-eth-wire-types = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" } +reth-evm-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" } +reth-exex = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" } +reth-exex-test-utils = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" } +reth-network-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" } +reth-network-peers = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" } +reth-node-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" } +reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" } +reth-prune-types = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" } +reth-rpc-eth-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" } +reth-transaction-pool = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" } # Foundry periphery foundry-blob-explorers = "0.17" @@ -128,14 +128,14 @@ alloy-rlp = "0.3.11" tempfile = "3.17.0" [patch.crates-io] -signet-bundle = { path = "../sdk/crates/bundle"} -signet-constants = { path = "../sdk/crates/constants"} -signet-evm = { path = "../sdk/crates/evm"} -signet-extract = { path = "../sdk/crates/extract"} -signet-journal = { path = "../sdk/crates/journal"} -signet-test-utils = { path = "../sdk/crates/test-utils"} -signet-tx-cache = { path = "../sdk/crates/tx-cache"} -signet-types = { path = "../sdk/crates/types"} -signet-zenith = { path = "../sdk/crates/zenith"} +# signet-bundle = { path = "../sdk/crates/bundle"} +# signet-constants = { path = "../sdk/crates/constants"} +# signet-evm = { path = "../sdk/crates/evm"} +# signet-extract = { path = "../sdk/crates/extract"} +# signet-journal = { path = "../sdk/crates/journal"} +# signet-test-utils = { path = "../sdk/crates/test-utils"} +# signet-tx-cache = { path = "../sdk/crates/tx-cache"} +# signet-types = { path = "../sdk/crates/types"} +# signet-zenith = { path = "../sdk/crates/zenith"} # init4-bin-base = { path = "../shared" } diff --git a/crates/block-processor/src/alias.rs b/crates/block-processor/src/alias.rs index 908b64d..8823b19 100644 --- a/crates/block-processor/src/alias.rs +++ b/crates/block-processor/src/alias.rs @@ -12,25 +12,32 @@ pub trait AliasOracle { fn should_alias(&self, address: Address) -> eyre::Result; } +/// Default implementation of [`AliasOracle`] for any type implementing +/// [`StateProvider`]. This implementation checks if the address has bytecode +/// associated with it, and if so, whether that bytecode matches the pattern +/// for a 7702 delegation contract. If it is a delegation contract, it is not +/// aliased; otherwise, it is aliased. impl AliasOracle for Box { fn should_alias(&self, address: Address) -> eyre::Result { + // No account at this address. let Some(acct) = self.basic_account(&address)? else { return Ok(false) }; + // Get the bytecode hash for this account. let bch = match acct.bytecode_hash { Some(hash) => hash, + // No bytecode hash; not a contract. None => return Ok(false), }; + // No code at this address. if bch == KECCAK_EMPTY { return Ok(false); } + // Fetch the code associated with this bytecode hash. let code = self .bytecode_by_hash(&bch)? .ok_or_eyre("code not found. This indicates a corrupted database")?; - // Check for 7702 delegations. - if code.len() != 23 || !code.bytecode().starts_with(&[0xef, 0x01, 0x00]) { - return Ok(true); - } - Ok(false) + // If not a 7702 delegation contract, alias it. + Ok(!code.is_eip7702()) } } @@ -62,6 +69,13 @@ impl AliasOracleFactory for Box { type Oracle = Box; fn create(&self) -> eyre::Result { + // NB: This becomes a problem if anyone ever birthday attacks a + // contract/EOA pair (c.f. EIP-3607). In practice this is unlikely to + // happen for the foreseeable future, and if it does we can revisit + // this decision. + // We considered taking the host height as an argument to this method, + // but this would require all nodes to be archive nodes in order to + // sync, which is less than ideal self.state_by_block_number_or_tag(alloy::eips::BlockNumberOrTag::Latest).map_err(Into::into) } } diff --git a/crates/node-tests/src/context.rs b/crates/node-tests/src/context.rs index 541357e..1cd1927 100644 --- a/crates/node-tests/src/context.rs +++ b/crates/node-tests/src/context.rs @@ -1,7 +1,7 @@ use crate::{ HostBlockSpec, NotificationSpec, NotificationWithSidecars, RuBlockSpec, - aliases::{CtxProvider, Log, TestCounterInstance, TestErc20Instance, TestLogInstance}, convert::ToRethPrimitive, + types::{CtxProvider, Log, TestCounterInstance, TestErc20Instance, TestLogInstance}, utils::create_test_provider_factory_with_chain_spec, }; use alloy::{ @@ -481,6 +481,7 @@ impl<'a> NonceChecks<'a> { } /// Assert that the nonce of the address has increased. + #[track_caller] pub fn assert_increase_by(&mut self, amount: u64) { let old_nonce = self.update_nonce(); let expected = old_nonce + amount; @@ -496,6 +497,7 @@ impl<'a> NonceChecks<'a> { } /// Assert that the nonce of the address has increased by 1. + #[track_caller] pub fn assert_incremented(&mut self) { self.assert_increase_by(1); } diff --git a/crates/node-tests/src/lib.rs b/crates/node-tests/src/lib.rs index 8a10d80..93dd860 100644 --- a/crates/node-tests/src/lib.rs +++ b/crates/node-tests/src/lib.rs @@ -11,9 +11,6 @@ #![deny(unused_must_use, rust_2018_idioms)] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] -/// Test aliases and type definitions. -pub mod aliases; - /// Test constants. pub mod constants; @@ -28,6 +25,9 @@ pub mod convert; pub mod rpc; pub use rpc::rpc_test; +/// Test aliases and type definitions. +pub mod types; + /// Utility functions and test harnesses. pub mod utils; pub use utils::run_test; diff --git a/crates/node-tests/src/rpc.rs b/crates/node-tests/src/rpc.rs index 2e55c86..b774cf1 100644 --- a/crates/node-tests/src/rpc.rs +++ b/crates/node-tests/src/rpc.rs @@ -1,4 +1,4 @@ -use crate::{aliases::TestCounterInstance, context::SignetTestContext, utils::run_test}; +use crate::{context::SignetTestContext, types::TestCounterInstance, utils::run_test}; /// A test helper that sets up a Signet test context, deploys the Counter /// contract, and then runs the provided async function `f` with the context and diff --git a/crates/node-tests/src/aliases.rs b/crates/node-tests/src/types.rs similarity index 100% rename from crates/node-tests/src/aliases.rs rename to crates/node-tests/src/types.rs diff --git a/crates/node-tests/tests/host_events.rs b/crates/node-tests/tests/host_events.rs index 8cff94f..c44b4d9 100644 --- a/crates/node-tests/tests/host_events.rs +++ b/crates/node-tests/tests/host_events.rs @@ -14,13 +14,16 @@ use serial_test::serial; use signet_db::{DbSignetEvent, SignetEvents}; use signet_node_tests::{ HostBlockSpec, SignetTestContext, - aliases::{Counter, TestCounterInstance}, constants::{DEFAULT_REWARD_ADDRESS, TEST_CONSTANTS}, run_test, + types::{Counter, TestCounterInstance}, utils::{adjust_usd_decimals, adjust_usd_decimals_u256}, }; use signet_test_utils::{chain::USDC_RECORD, contracts::counter::COUNTER_BYTECODE}; -use signet_types::constants::{HostPermitted, RollupPermitted}; +use signet_types::{ + constants::{HostPermitted, RollupPermitted}, + unalias_address, +}; use signet_zenith::{MINTER_ADDRESS, Passage, Transactor, mintCall}; alloy::sol! { @@ -207,11 +210,24 @@ async fn test_transact() { run_test(|ctx| async move { // set up user let user = ctx.addresses[0]; + + // Getting a little cute here. We ensure that the ALIASED version is + // one of the standard test addresses, so we don't have to set up any + // extra accounts. + let aliased = ctx.addresses[1]; + let host_contract = unalias_address(aliased); + + // Indicate to the block processor that this address should be aliased + ctx.set_should_alias(host_contract, true); + let mut user_nonce = ctx.track_nonce(user, Some("user")); let mut user_bal = ctx.track_balance(user, Some("user")); + let mut aliased_nonce = ctx.track_nonce(aliased, Some("aliased")); + let mut aliased_bal = ctx.track_balance(aliased, Some("aliased")); + // Deploy a contract to interact with - let deployer = ctx.addresses[1]; + let deployer = ctx.addresses[2]; // Assert that the counter is zero let contract = ctx.deploy_counter(deployer).await; @@ -219,19 +235,19 @@ async fn test_transact() { assert_eq!(contract.count().call().await.unwrap(), U256::ZERO); // Transact that calls the context and increments it. - let block = HostBlockSpec::new(ctx.constants()).simple_transact( - user, - contract_addr, - Counter::incrementCall::SELECTOR, - 0, - ); + let block = HostBlockSpec::new(ctx.constants()) + .simple_transact(user, contract_addr, Counter::incrementCall::SELECTOR, 0) + .simple_transact(host_contract, contract_addr, Counter::incrementCall::SELECTOR, 0); ctx.process_block(block).await.unwrap(); user_nonce.assert_incremented(); user_bal.assert_decrease(); - assert_eq!(contract.count().call().await.unwrap(), U256::from(1)); + aliased_nonce.assert_incremented(); + aliased_bal.assert_decrease(); + + assert_eq!(contract.count().call().await.unwrap(), U256::from(2)); // check the RPC response let block = ctx @@ -258,6 +274,20 @@ async fn test_transact() { assert_eq!(transact_tx.to().unwrap(), contract_addr); assert_eq!(transact_tx.value(), U256::ZERO); assert_eq!(transact_tx.input(), &Bytes::from(Counter::incrementCall::SELECTOR)); + + let aliased_transact_tx = &txns[1]; + assert_eq!(aliased_transact_tx.from(), aliased); + assert_eq!(aliased_transact_tx.to().unwrap(), contract_addr); + assert_eq!(aliased_transact_tx.value(), U256::ZERO); + assert_eq!(aliased_transact_tx.input(), &Bytes::from(Counter::incrementCall::SELECTOR)); + + let aliased_tx_hash = aliased_transact_tx.tx_hash(); + let aliased_transact_tx = + ctx.alloy_provider.get_transaction_by_hash(aliased_tx_hash).await.unwrap().unwrap(); + assert_eq!(aliased_transact_tx.from(), aliased); + assert_eq!(aliased_transact_tx.to().unwrap(), contract_addr); + assert_eq!(aliased_transact_tx.value(), U256::ZERO); + assert_eq!(aliased_transact_tx.input(), &Bytes::from(Counter::incrementCall::SELECTOR)); }) .await; } diff --git a/crates/node-tests/tests/orders.rs b/crates/node-tests/tests/orders.rs index 04b6dbc..e9b8822 100644 --- a/crates/node-tests/tests/orders.rs +++ b/crates/node-tests/tests/orders.rs @@ -8,9 +8,8 @@ use alloy::{ }; use serial_test::serial; use signet_node_tests::{ - HostBlockSpec, RuBlockSpec, SignetTestContext, - aliases::{Erc20, TestErc20Instance}, - run_test, + HostBlockSpec, RuBlockSpec, SignetTestContext, run_test, + types::{Erc20, TestErc20Instance}, }; use signet_types::constants::HostPermitted; use signet_zenith::RollupOrders; diff --git a/crates/node-tests/tests/rpc.rs b/crates/node-tests/tests/rpc.rs index 3aed297..89f8862 100644 --- a/crates/node-tests/tests/rpc.rs +++ b/crates/node-tests/tests/rpc.rs @@ -17,9 +17,9 @@ use reth::providers::{BlockNumReader, BlockReader, TransactionsProvider}; use serial_test::serial; use signet_node_tests::{ SignetTestContext, - aliases::{Counter, TestCounterInstance}, constants::TEST_CONSTANTS, rpc_test, + types::{Counter, TestCounterInstance}, }; use signet_test_utils::contracts::counter::{COUNTER_BYTECODE, COUNTER_DEPLOY_CODE}; use tokio::try_join; diff --git a/crates/node-tests/tests/rpc_debug.rs b/crates/node-tests/tests/rpc_debug.rs index 437ce0e..90d240a 100644 --- a/crates/node-tests/tests/rpc_debug.rs +++ b/crates/node-tests/tests/rpc_debug.rs @@ -4,7 +4,7 @@ use reth::{ rpc::types::trace::geth::{CallConfig, GethDebugTracingOptions}, }; use serial_test::serial; -use signet_node_tests::{aliases::Counter::incrementCall, rpc::rpc_test}; +use signet_node_tests::{rpc::rpc_test, types::Counter::incrementCall}; use signet_test_utils::specs::{HostBlockSpec, RuBlockSpec}; #[serial] diff --git a/crates/node-tests/tests/submit-tx.rs b/crates/node-tests/tests/submit-tx.rs index d8b3467..adb742c 100644 --- a/crates/node-tests/tests/submit-tx.rs +++ b/crates/node-tests/tests/submit-tx.rs @@ -6,9 +6,7 @@ use alloy::{ rpc::types::eth::TransactionRequest, }; use serial_test::serial; -use signet_node_tests::{ - HostBlockSpec, RuBlockSpec, aliases::TestCounterInstance, utils::run_test, -}; +use signet_node_tests::{HostBlockSpec, RuBlockSpec, types::TestCounterInstance, utils::run_test}; use signet_test_utils::contracts::counter::{COUNTER_BYTECODE, COUNTER_DEPLOY_CODE}; const USER_A: Address = Address::repeat_byte(0x39); From 2259df581d1048d7bf08dc7ef9e0fbde8d532ab6 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 5 Nov 2025 12:36:30 -0500 Subject: [PATCH 7/9] fix: use revm spec consistently --- crates/block-processor/src/lib.rs | 3 ++ crates/block-processor/src/utils.rs | 37 ++++++++++++++++++++++ crates/block-processor/src/v1/processor.rs | 8 ++--- crates/node-config/Cargo.toml | 1 + crates/node-config/src/core.rs | 8 ++--- crates/rpc/Cargo.toml | 2 +- crates/rpc/src/ctx/signet.rs | 2 +- 7 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 crates/block-processor/src/utils.rs diff --git a/crates/block-processor/src/lib.rs b/crates/block-processor/src/lib.rs index 87341a2..d836442 100644 --- a/crates/block-processor/src/lib.rs +++ b/crates/block-processor/src/lib.rs @@ -16,6 +16,9 @@ pub(crate) mod metrics; mod alias; pub use alias::{AliasOracle, AliasOracleFactory}; +mod utils; +pub use utils::revm_spec; + mod v1; pub use v1::SignetBlockProcessor as SignetBlockProcessorV1; diff --git a/crates/block-processor/src/utils.rs b/crates/block-processor/src/utils.rs new file mode 100644 index 0000000..4341433 --- /dev/null +++ b/crates/block-processor/src/utils.rs @@ -0,0 +1,37 @@ +use reth::revm::primitives::hardfork::SpecId; +use reth_chainspec::EthereumHardforks; + +/// Equivalent to [`reth_evm_ethereum::revm_spec`], however, always starts at +/// [`SpecId::PRAGUE`] and transitions to [`SpecId::OSAKA`]. +pub fn revm_spec(chain_spec: &reth::chainspec::ChainSpec, timestamp: u64) -> SpecId { + if chain_spec.is_osaka_active_at_timestamp(timestamp) { SpecId::OSAKA } else { SpecId::PRAGUE } +} + +/// This is simply a compile-time assertion to ensure that all SpecIds are +/// covered in the match. When this fails to compile, it indicates that a new +/// hardfork has been added and [`revm_spec`] needs to be updated. +#[allow(dead_code)] +const fn assert_in_range(spec_id: SpecId) { + match spec_id { + SpecId::FRONTIER + | SpecId::FRONTIER_THAWING + | SpecId::HOMESTEAD + | SpecId::DAO_FORK + | SpecId::TANGERINE + | SpecId::SPURIOUS_DRAGON + | SpecId::BYZANTIUM + | SpecId::CONSTANTINOPLE + | SpecId::PETERSBURG + | SpecId::ISTANBUL + | SpecId::MUIR_GLACIER + | SpecId::BERLIN + | SpecId::LONDON + | SpecId::ARROW_GLACIER + | SpecId::GRAY_GLACIER + | SpecId::MERGE + | SpecId::SHANGHAI + | SpecId::CANCUN + | SpecId::PRAGUE + | SpecId::OSAKA => {} + } +} diff --git a/crates/block-processor/src/v1/processor.rs b/crates/block-processor/src/v1/processor.rs index fd5aa30..66ada78 100644 --- a/crates/block-processor/src/v1/processor.rs +++ b/crates/block-processor/src/v1/processor.rs @@ -14,7 +14,7 @@ use reth::{ }, revm::{database::StateProviderDatabase, db::StateBuilder}, }; -use reth_chainspec::{ChainSpec, EthereumHardforks}; +use reth_chainspec::ChainSpec; use reth_node_api::{FullNodeComponents, NodeTypes}; use signet_blobber::{CacheHandle, ExtractableChainShim}; use signet_constants::SignetSystemConstants; @@ -80,11 +80,7 @@ where /// Get the active spec id at the given timestamp. fn spec_id(&self, timestamp: u64) -> SpecId { - if self.chain_spec.is_prague_active_at_timestamp(timestamp) { - SpecId::PRAGUE - } else { - SpecId::CANCUN - } + crate::revm_spec(&self.chain_spec, timestamp) } /// Make a [`StateProviderDatabase`] from the read-write provider, suitable diff --git a/crates/node-config/Cargo.toml b/crates/node-config/Cargo.toml index 0842f4b..5774f5e 100644 --- a/crates/node-config/Cargo.toml +++ b/crates/node-config/Cargo.toml @@ -28,6 +28,7 @@ serde.workspace = true tracing.workspace = true trevm.workspace = true signet-genesis.workspace = true +signet-block-processor.workspace = true [features] test_utils = ["dep:reth-db", "reth-db/test-utils"] diff --git a/crates/node-config/src/core.rs b/crates/node-config/src/core.rs index d0f5aa2..3954aac 100644 --- a/crates/node-config/src/core.rs +++ b/crates/node-config/src/core.rs @@ -1,7 +1,7 @@ use alloy::genesis::Genesis; use init4_bin_base::utils::{calc::SlotCalculator, from_env::FromEnv}; use reth::providers::providers::StaticFileProvider; -use reth_chainspec::{ChainSpec, EthereumHardforks}; +use reth_chainspec::ChainSpec; use reth_node_api::NodePrimitives; use signet_blobber::BlobFetcherConfig; use signet_genesis::GenesisSpec; @@ -215,11 +215,7 @@ impl SignetNodeConfig { /// Get the current spec id for the Signet Node chain. pub fn spec_id(&self, timestamp: u64) -> SpecId { - if self.chain_spec().is_prague_active_at_timestamp(timestamp) { - SpecId::PRAGUE - } else { - SpecId::CANCUN - } + signet_block_processor::revm_spec(self.chain_spec(), timestamp) } } diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index c579fa0..6594a41 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -27,7 +27,6 @@ reth.workspace = true reth-chainspec.workspace = true reth-db.workspace = true reth-db-common.workspace = true -reth-evm-ethereum.workspace = true reth-node-api.workspace = true reth-rpc-eth-api.workspace = true @@ -45,6 +44,7 @@ tracing.workspace = true serde_json.workspace = true futures-util = "0.3.31" itertools.workspace = true +signet-block-processor.workspace = true [dev-dependencies] signet-zenith.workspace = true diff --git a/crates/rpc/src/ctx/signet.rs b/crates/rpc/src/ctx/signet.rs index 1a06e91..113f1af 100644 --- a/crates/rpc/src/ctx/signet.rs +++ b/crates/rpc/src/ctx/signet.rs @@ -173,7 +173,7 @@ where /// Get the EVM spec ID for a given block. pub fn evm_spec_id(&self, header: &Header) -> SpecId { - reth_evm_ethereum::revm_spec(&self.chain_spec(), header) + signet_block_processor::revm_spec(&self.chain_spec(), header.timestamp()) } /// Access the subscription manager. From 19322531a08abb2bccecb91be05481251d84892f Mon Sep 17 00:00:00 2001 From: James Date: Wed, 5 Nov 2025 13:23:14 -0500 Subject: [PATCH 8/9] chore: bump to compat signet-sdk --- Cargo.toml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 77b999d..a44fe00 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,22 +46,22 @@ signet-rpc = { version = "0.14", path = "crates/rpc" } init4-bin-base = { version = "0.13.1", features = ["alloy"] } -signet-bundle = "0.14" -signet-constants = "0.14" -signet-evm = "0.14" -signet-extract = "0.14" -signet-test-utils = "0.14" -signet-tx-cache = "0.14" -signet-types = "0.14" -signet-zenith = "0.14" -signet-journal = "0.14" +signet-bundle = "0.15" +signet-constants = "0.15" +signet-evm = "0.15" +signet-extract = "0.15" +signet-test-utils = "0.15" +signet-tx-cache = "0.15" +signet-types = "0.15" +signet-zenith = "0.15" +signet-journal = "0.15" # ajj ajj = { version = "0.3.4" } # trevm -trevm = { version = "0.29.0", features = ["full_env_cfg"] } -revm-inspectors = "0.30.0" # should be 1 more than trevm version, usually +trevm = { version = "0.31.0", features = ["full_env_cfg"] } +revm-inspectors = "0.32.0" # should be 1 more than trevm version, usually # Alloy periphery crates alloy = { version = "1.0.35", features = [ From 18ea175f5af156a70c1018675afcb64155ec7743 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 5 Nov 2025 14:32:27 -0500 Subject: [PATCH 9/9] chore: bump reth and update everything --- Cargo.toml | 20 +-- crates/block-processor/src/utils.rs | 11 +- crates/db/src/provider.rs | 202 +++++++++------------------- crates/db/src/traits.rs | 49 ++----- crates/db/tests/db.rs | 19 +-- crates/node/src/node.rs | 5 +- 6 files changed, 101 insertions(+), 205 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a44fe00..a7c0179 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,15 +46,15 @@ signet-rpc = { version = "0.14", path = "crates/rpc" } init4-bin-base = { version = "0.13.1", features = ["alloy"] } -signet-bundle = "0.15" -signet-constants = "0.15" -signet-evm = "0.15" -signet-extract = "0.15" -signet-test-utils = "0.15" -signet-tx-cache = "0.15" -signet-types = "0.15" -signet-zenith = "0.15" -signet-journal = "0.15" +signet-bundle = "0.14" +signet-constants = "0.14" +signet-evm = "0.14" +signet-extract = "0.14" +signet-test-utils = "0.14" +signet-tx-cache = "0.14" +signet-types = "0.14" +signet-zenith = "0.14" +signet-journal = "0.14" # ajj ajj = { version = "0.3.4" } @@ -127,7 +127,7 @@ uuid = "1.16.0" alloy-rlp = "0.3.11" tempfile = "3.17.0" -[patch.crates-io] +# [patch.crates-io] # signet-bundle = { path = "../sdk/crates/bundle"} # signet-constants = { path = "../sdk/crates/constants"} # signet-evm = { path = "../sdk/crates/evm"} diff --git a/crates/block-processor/src/utils.rs b/crates/block-processor/src/utils.rs index 4341433..f6140d6 100644 --- a/crates/block-processor/src/utils.rs +++ b/crates/block-processor/src/utils.rs @@ -4,7 +4,13 @@ use reth_chainspec::EthereumHardforks; /// Equivalent to [`reth_evm_ethereum::revm_spec`], however, always starts at /// [`SpecId::PRAGUE`] and transitions to [`SpecId::OSAKA`]. pub fn revm_spec(chain_spec: &reth::chainspec::ChainSpec, timestamp: u64) -> SpecId { - if chain_spec.is_osaka_active_at_timestamp(timestamp) { SpecId::OSAKA } else { SpecId::PRAGUE } + if chain_spec.is_amsterdam_active_at_timestamp(timestamp) { + SpecId::AMSTERDAM + } else if chain_spec.is_osaka_active_at_timestamp(timestamp) { + SpecId::OSAKA + } else { + SpecId::PRAGUE + } } /// This is simply a compile-time assertion to ensure that all SpecIds are @@ -32,6 +38,7 @@ const fn assert_in_range(spec_id: SpecId) { | SpecId::SHANGHAI | SpecId::CANCUN | SpecId::PRAGUE - | SpecId::OSAKA => {} + | SpecId::OSAKA + | SpecId::AMSTERDAM => {} } } diff --git a/crates/db/src/provider.rs b/crates/db/src/provider.rs index fa9d17a..13c6d4f 100644 --- a/crates/db/src/provider.rs +++ b/crates/db/src/provider.rs @@ -4,15 +4,15 @@ use crate::{ traits::RuWriter, }; use alloy::{ - consensus::{BlockHeader, TxReceipt}, - primitives::{Address, B256, BlockNumber, U256, map::HashSet}, + consensus::BlockHeader, + primitives::{Address, B256, BlockNumber}, }; use reth::{ primitives::StaticFileSegment, providers::{ BlockBodyIndicesProvider, BlockNumReader, BlockReader, BlockWriter, Chain, DBProvider, HistoryWriter, OriginalValuesKnown, ProviderError, ProviderResult, StageCheckpointWriter, - StateWriter, StaticFileProviderFactory, StaticFileWriter, StorageLocation, + StateWriter, StaticFileProviderFactory, StaticFileWriter, }, }; use reth_db::{ @@ -30,7 +30,7 @@ use signet_zenith::{ Transactor::Transact, Zenith, }; -use std::ops::RangeInclusive; +use std::ops::{Not, RangeInclusive}; use tracing::{debug, instrument, trace, warn}; impl RuWriter for SignetDbRw @@ -144,14 +144,13 @@ where header: Option, block: &RecoveredBlock, journal_hash: B256, - write_to: StorageLocation, ) -> ProviderResult { // Implementation largely copied from // `BlockWriter::insert_block` // in `reth/crates/storage/provider/src/providers/database/provider.rs` // duration metrics have been removed // - // Last reviewed at tag v1.8.1 + // Last reviewed at tag v1.9.0 let block_number = block.number(); // SIGNET-SPECIFIC @@ -159,7 +158,6 @@ where if let Some(header) = header { self.insert_signet_header(header, block_number)?; } - // SIGNET-SPECIFIC // Put journal hash into the DB self.tx_ref().put::(block_number, journal_hash)?; @@ -167,24 +165,10 @@ where let block_hash = block.block.header.hash(); let block_header = block.block.header.header(); - if write_to.database() { - self.tx_ref().put::(block_number, block_hash)?; - self.tx_ref().put::(block_number, block_header.clone())?; - // NB: while this is meaningless for zenith blocks, it is necessary for - // the RPC server to function properly. If the TTD for a block is not - // set, the RPC server will return an error indicating that the block - // is not found. - self.tx_ref() - .put::(block_number, U256::ZERO.into())?; - } - - if write_to.static_files() { - let sf = self.static_file_provider(); - let mut writer = sf.get_writer(block_number, StaticFileSegment::Headers)?; - writer.append_header(block_header, U256::ZERO, &block_hash)?; - } + self.static_file_provider() + .get_writer(block_number, StaticFileSegment::Headers)? + .append_header(block_header, &block_hash)?; - // Append the block number corresponding to a header on the DB self.tx_ref().put::(block_hash, block_number)?; let mut next_tx_num = self @@ -211,7 +195,7 @@ where next_tx_num += 1; } - self.append_signet_block_body((block_number, block), write_to)?; + self.append_signet_block_body((block_number, block))?; debug!(?block_number, "Inserted block"); @@ -219,50 +203,35 @@ where } /// Appends the body of a signet block to the database. - fn append_signet_block_body( - &self, - body: (BlockNumber, &RecoveredBlock), - write_to: StorageLocation, - ) -> ProviderResult<()> { + fn append_signet_block_body(&self, body: (BlockNumber, &RecoveredBlock)) -> ProviderResult<()> { // Implementation largely copied from // `DatabaseProvider::append_block_bodies` // in `reth/crates/storage/provider/src/providers/database/provider.rs` // duration metrics have been removed, and the implementation has been // modified to work with a single signet block. // - // last reviewed at tag v1.8.1 + // last reviewed at tag v1.9.0 + let from_block = body.0; let sf = self.static_file_provider(); // Initialize writer if we will be writing transactions to staticfiles - let mut tx_static_writer = write_to - .static_files() - .then(|| sf.get_writer(body.0, StaticFileSegment::Transactions)) - .transpose()?; + let mut tx_writer = sf.get_writer(from_block, StaticFileSegment::Transactions)?; let mut block_indices_cursor = self.tx_ref().cursor_write::()?; let mut tx_block_cursor = self.tx_ref().cursor_write::()?; - // Initialize curosr if we will be writing transactions to database - let mut tx_cursor = write_to - .database() - .then(|| self.tx_ref().cursor_write::()) - .transpose()?; - let block_number = body.0; let block = body.1; // Get id for the next tx_num or zero if there are no transactions. let mut next_tx_num = tx_block_cursor.last()?.map(|(n, _)| n + 1).unwrap_or_default(); - // Increment block on static file header if we're writing to static files. - if let Some(writer) = tx_static_writer.as_mut() { - writer.increment_block(block_number)?; - } + // Increment block on static file header + tx_writer.increment_block(block_number)?; - let tx_count = block.block.body.transactions.len(); - let block_indices = - StoredBlockBodyIndices { first_tx_num: next_tx_num, tx_count: tx_count as u64 }; + let tx_count = block.block.body.transactions.len() as u64; + let block_indices = StoredBlockBodyIndices { first_tx_num: next_tx_num, tx_count }; // insert block meta block_indices_cursor.append(block_number, &block_indices)?; @@ -274,13 +243,7 @@ where // Write transactions for transaction in block.block.body.transactions() { - if let Some(writer) = tx_static_writer.as_mut() { - writer.append_transaction(next_tx_num, transaction)?; - } - - if let Some(cursor) = tx_cursor.as_mut() { - cursor.append(next_tx_num, transaction)?; - } + tx_writer.append_transaction(next_tx_num, transaction)?; // Increment transaction id for each transaction next_tx_num += 1; @@ -326,7 +289,6 @@ where fn take_signet_headers_above( &self, target: BlockNumber, - _remove_from: StorageLocation, ) -> ProviderResult> { // Implementation largely copied from // `DatabaseProvider::get_or_take` @@ -347,11 +309,7 @@ where } /// Remove [`Zenith::BlockHeader`] objects above the specified height from the DB. - fn remove_signet_headers_above( - &self, - target: BlockNumber, - _remove_from: StorageLocation, - ) -> ProviderResult<()> { + fn remove_signet_headers_above(&self, target: BlockNumber) -> ProviderResult<()> { self.remove::(target + 1..)?; Ok(()) } @@ -373,11 +331,10 @@ where fn take_signet_events_above( &self, target: BlockNumber, - remove_from: StorageLocation, ) -> ProviderResult> { let range = target + 1..=self.last_block_number()?; let items = self.get_signet_events(range)?; - self.remove_signet_events_above(target, remove_from)?; + self.remove_signet_events_above(target)?; Ok(items) } @@ -385,11 +342,7 @@ where /// [`Transactor::Transact`] events above the specified height from the DB. /// /// [`Transactor::Transact`]: signet_zenith::Transactor::Transact - fn remove_signet_events_above( - &self, - target: BlockNumber, - _remove_from: StorageLocation, - ) -> ProviderResult<()> { + fn remove_signet_events_above(&self, target: BlockNumber) -> ProviderResult<()> { self.remove::(target + 1..)?; Ok(()) } @@ -419,15 +372,15 @@ where // in `reth/crates/storage/provider/src/providers/database/provider.rs` // duration metrics have been removed // - // last reviewed at tag v1.8.1 + // last reviewed at tag v1.9.0 let BlockResult { sealed_block: block, execution_outcome, .. } = block_result; let ru_height = block.number(); - self.insert_signet_block(header, block, journal_hash, StorageLocation::Database)?; + self.insert_signet_block(header, block, journal_hash)?; // Write the state and match the storage location that Reth uses. - self.ru_write_state(execution_outcome, OriginalValuesKnown::No, StorageLocation::Database)?; + self.ru_write_state(execution_outcome, OriginalValuesKnown::No)?; // NB: At this point, reth writes hashed state and trie updates. Signet // skips this. We re-use these tables to write the enters, enter tokens, @@ -462,22 +415,18 @@ where } #[instrument(skip(self))] - fn ru_take_blocks_and_execution_above( - &self, - target: BlockNumber, - remove_from: StorageLocation, - ) -> ProviderResult { + fn ru_take_blocks_and_execution_above(&self, target: BlockNumber) -> ProviderResult { // Implementation largely copied from // `BlockExecutionWriter::take_block_and_execution_above` // in `reth/crates/storage/provider/src/providers/database/provider.rs` // - // last reviewed at tag v1.8.1 + // last reviewed at tag v1.9.0 let range = target + 1..=self.last_block_number()?; // This block is copied from `unwind_trie_state_range` // - // last reviewed at tag v1.8.1 + // last reviewed at tag v1.9.0 { let changed_accounts = self .tx_ref() @@ -489,14 +438,14 @@ where // root calculation, which we don't use. self.unwind_account_history_indices(changed_accounts.iter())?; - let storage_range = BlockNumberAddress::range(range.clone()); + let storage_start = BlockNumberAddress((target, Address::ZERO)); // Unwind storage history indices. Similarly, we don't need to // unwind storage hashes, since we don't use them. let changed_storages = self .tx_ref() .cursor_read::()? - .walk_range(storage_range)? + .walk_range(storage_start..)? .collect::, _>>()?; self.unwind_storage_history_indices(changed_storages.iter().copied())?; @@ -506,7 +455,7 @@ where trace!("trie state unwound"); - let execution_state = self.take_state_above(target, remove_from)?; + let execution_state = self.take_state_above(target)?; trace!("state taken"); @@ -517,14 +466,14 @@ where // remove block bodies it is needed for both get block range and get block execution results // that is why it is deleted afterwards. - self.remove_blocks_above(target, remove_from)?; + self.remove_blocks_above(target)?; trace!("blocks removed"); + // SIGNET-SPECIFIC // This is a Signet-specific addition that removes the enters, // entertokens, zenith headers, and transact events. - let ru_info = - self.take_extraction_results_above(target, remove_from)?.into_iter().collect(); + let ru_info = self.take_extraction_results_above(target)?.into_iter().collect(); trace!("extraction results taken"); @@ -539,51 +488,53 @@ where } #[instrument(skip(self))] - fn ru_remove_blocks_and_execution_above( - &self, - block: BlockNumber, - remove_from: StorageLocation, - ) -> ProviderResult<()> { + fn ru_remove_blocks_and_execution_above(&self, target: BlockNumber) -> ProviderResult<()> { // Implementation largely copied from // `BlockExecutionWriter::remove_block_and_execution_above` // in `reth/crates/storage/provider/src/providers/database/provider.rs` // duration metrics have been removed // - // last reviewed at tag v1.8.1 + // last reviewed at tag v1.9.0 + + let range = target + 1..=self.last_block_number()?; // This block is copied from `unwind_trie_state_range` // - // last reviewed at tag v1.8.1 + // last reviewed at tag v1.9.0 { - let range = block + 1..=self.last_block_number()?; let changed_accounts = self .tx_ref() .cursor_read::()? .walk_range(range.clone())? .collect::, _>>()?; - + // There's no need to also unwind account hashes, since that is + // only useful for filling intermediate tables that deal with state + // root calculation, which we don't use. self.unwind_account_history_indices(changed_accounts.iter())?; - let storage_range = BlockNumberAddress::range(range.clone()); + let storage_start = BlockNumberAddress((target, Address::ZERO)); - // Unwind storage history indices. + // Unwind storage history indices. Similarly, we don't need to + // unwind storage hashes, since we don't use them. let changed_storages = self .tx_ref() .cursor_read::()? - .walk_range(storage_range)? + .walk_range(storage_start..)? .collect::, _>>()?; self.unwind_storage_history_indices(changed_storages.iter().copied())?; + + // We also skip calculating the reverted root here. } - self.remove_state_above(block, remove_from)?; - self.remove_blocks_above(block, remove_from)?; + self.remove_state_above(target)?; + self.remove_blocks_above(target)?; // Signet specific: - self.remove_extraction_results_above(block, remove_from)?; + self.remove_extraction_results_above(target)?; // Update pipeline stages - self.update_pipeline_stages(block, true)?; + self.update_pipeline_stages(target, true)?; Ok(()) } @@ -592,13 +543,12 @@ where &self, execution_outcome: &signet_evm::ExecutionOutcome, is_value_known: OriginalValuesKnown, - write_receipts_to: StorageLocation, ) -> ProviderResult<()> { // Implementation largely copied from // `StateWriter::write_state` for `DatabaseProvider` // in `reth/crates/storage/provider/src/providers/database/provider.rs` // - // Last reviewed at tag v1.8.1 + // Last reviewed at tag v1.9.0 let first_block = execution_outcome.first_block(); let block_count = execution_outcome.len() as u64; let last_block = execution_outcome.last_block(); @@ -633,14 +583,8 @@ where // // We are writing to database if requested or if there's any kind of receipt pruning // configured - let mut receipts_cursor = (write_receipts_to.database() || has_receipts_pruning) - .then(|| self.tx_ref().cursor_write::>()) - .transpose()?; - - // Prepare receipts static writer if we are going to write receipts to static files - // - // We are writing to static files if requested and if there's no receipt pruning configured - let should_static = write_receipts_to.static_files() && !has_receipts_pruning; + let mut receipts_cursor = + self.tx_ref().cursor_write::>()?; // SIGNET: This is a departure from Reth's implementation. Becuase their // impl is on `DatabaseProvider`, it has access to the static file @@ -649,27 +593,18 @@ where // to borrow from the inner, only to clone it. So we break up the // static file provider into a separate variable, and then use it to // create the static file writer. - let sfp = should_static.then(|| self.0.static_file_provider()); - let mut receipts_static_writer = sfp - .as_ref() - .map(|sfp| sfp.get_writer(first_block, StaticFileSegment::Receipts)) - .transpose()?; + let sfp = self.0.static_file_provider(); - let has_contract_log_filter = !self.prune_modes_ref().receipts_log_filter.is_empty(); - let contract_log_pruner = - self.prune_modes_ref().receipts_log_filter.group_by_block(tip, None)?; + let mut receipts_static_writer = has_receipts_pruning + .not() + .then(|| sfp.get_writer(first_block, StaticFileSegment::Receipts)) + .transpose()?; // All receipts from the last 128 blocks are required for blockchain tree, even with // [`PruneSegment::ContractLogs`]. let prunable_receipts = PruneMode::Distance(MINIMUM_PRUNING_DISTANCE).should_prune(first_block, tip); - // Prepare set of addresses which logs should not be pruned. - let mut allowed_addresses: HashSet = HashSet::new(); - for (_, addresses) in contract_log_pruner.range(..first_block) { - allowed_addresses.extend(addresses.iter().copied()); - } - for (idx, (receipts, first_tx_index)) in execution_outcome.receipts().iter().zip(block_indices).enumerate() { @@ -690,28 +625,13 @@ where continue; } - // If there are new addresses to retain after this block number, track them - if let Some(new_addresses) = contract_log_pruner.get(&block_number) { - allowed_addresses.extend(new_addresses.iter().copied()); - } - for (idx, receipt) in receipts.iter().map(DataCompat::clone_convert).enumerate() { let receipt_idx = first_tx_index + idx as u64; - // Skip writing receipt if log filter is active and it does not have any logs to - // retain - if prunable_receipts - && has_contract_log_filter - && !receipt.logs().iter().any(|log| allowed_addresses.contains(&log.address)) - { - continue; - } if let Some(writer) = &mut receipts_static_writer { writer.append_receipt(receipt_idx, &receipt)?; - } - - if let Some(cursor) = &mut receipts_cursor { - cursor.append(receipt_idx, &receipt)?; + } else { + receipts_cursor.append(receipt_idx, &receipt)?; } } } diff --git a/crates/db/src/traits.rs b/crates/db/src/traits.rs index 5de0f2c..04efed9 100644 --- a/crates/db/src/traits.rs +++ b/crates/db/src/traits.rs @@ -1,7 +1,7 @@ use crate::{DbExtractionResults, DbSignetEvent, RuChain, SignetDbRw}; use alloy::primitives::{B256, BlockNumber}; use itertools::Itertools; -use reth::providers::{OriginalValuesKnown, ProviderResult, StorageLocation}; +use reth::providers::{OriginalValuesKnown, ProviderResult}; use reth_db::models::StoredBlockBodyIndices; use signet_evm::BlockResult; use signet_node_types::NodeTypesDbTrait; @@ -44,15 +44,10 @@ pub trait RuWriter { header: Option, block: &RecoveredBlock, journal_hash: B256, - write_to: StorageLocation, ) -> ProviderResult; /// Append a zenith block body to the DB. - fn append_signet_block_body( - &self, - body: (BlockNumber, &RecoveredBlock), - write_to: StorageLocation, - ) -> ProviderResult<()>; + fn append_signet_block_body(&self, body: (BlockNumber, &RecoveredBlock)) -> ProviderResult<()>; /// Get zenith headers from the DB. fn get_signet_headers( @@ -64,15 +59,10 @@ pub trait RuWriter { fn take_signet_headers_above( &self, target: BlockNumber, - remove_from: StorageLocation, ) -> ProviderResult>; /// Remove [`Zenith::BlockHeader`] objects above the specified height from the DB. - fn remove_signet_headers_above( - &self, - target: BlockNumber, - remove_from: StorageLocation, - ) -> ProviderResult<()>; + fn remove_signet_headers_above(&self, target: BlockNumber) -> ProviderResult<()>; /// Store an enter event in the DB. fn insert_enter(&self, height: u64, index: u64, exit: Passage::Enter) -> ProviderResult<()>; @@ -158,16 +148,11 @@ pub trait RuWriter { fn take_signet_events_above( &self, target: BlockNumber, - remove_from: StorageLocation, ) -> ProviderResult>; /// Remove [`Passage::EnterToken`], [`Passage::Enter`] and /// [`Transactor::Transact`] events above the specified height from the DB. - fn remove_signet_events_above( - &self, - target: BlockNumber, - remove_from: StorageLocation, - ) -> ProviderResult<()>; + fn remove_signet_events_above(&self, target: BlockNumber) -> ProviderResult<()>; /// Get extraction results from the DB. fn get_extraction_results( @@ -214,13 +199,12 @@ pub trait RuWriter { fn take_extraction_results_above( &self, target: BlockNumber, - remove_from: StorageLocation, ) -> ProviderResult> { let range = target..=(1 + self.last_block_number()?); let items = self.get_extraction_results(range)?; trace!(count = items.len(), "got extraction results"); - self.remove_extraction_results_above(target, remove_from)?; + self.remove_extraction_results_above(target)?; trace!("removed extraction results"); Ok(items) } @@ -232,13 +216,9 @@ pub trait RuWriter { /// - [`Passage::Enter`] events /// - [`Transactor::Transact`] events /// - [`Passage::EnterToken`] events - fn remove_extraction_results_above( - &self, - target: BlockNumber, - remove_from: StorageLocation, - ) -> ProviderResult<()> { - self.remove_signet_headers_above(target, remove_from)?; - self.remove_signet_events_above(target, remove_from)?; + fn remove_extraction_results_above(&self, target: BlockNumber) -> ProviderResult<()> { + self.remove_signet_headers_above(target)?; + self.remove_signet_events_above(target)?; Ok(()) } @@ -256,18 +236,10 @@ pub trait RuWriter { /// Take the block and execution range from the DB, reverting the blocks /// and returning the removed information - fn ru_take_blocks_and_execution_above( - &self, - target: BlockNumber, - remove_from: StorageLocation, - ) -> ProviderResult; + fn ru_take_blocks_and_execution_above(&self, target: BlockNumber) -> ProviderResult; /// Remove the block and execution range from the DB. - fn ru_remove_blocks_and_execution_above( - &self, - target: BlockNumber, - remove_from: StorageLocation, - ) -> ProviderResult<()>; + fn ru_remove_blocks_and_execution_above(&self, target: BlockNumber) -> ProviderResult<()>; /// Write the state of the rollup to the database. /// @@ -279,7 +251,6 @@ pub trait RuWriter { &self, execution_outcome: &signet_evm::ExecutionOutcome, is_value_known: OriginalValuesKnown, - write_receipts_to: StorageLocation, ) -> ProviderResult<()>; } diff --git a/crates/db/tests/db.rs b/crates/db/tests/db.rs index f59cbfb..3a08323 100644 --- a/crates/db/tests/db.rs +++ b/crates/db/tests/db.rs @@ -55,19 +55,20 @@ fn test_insert_signet_block() { senders: std::iter::repeat_n(Address::repeat_byte(0x33), 10).collect(), }; - writer - .insert_signet_block(header, &block, journal_hash, reth::providers::StorageLocation::Both) - .unwrap(); + writer.insert_signet_block(header, &block, journal_hash).unwrap(); + writer.commit().unwrap(); + + let reader = factory.provider_rw().unwrap(); // Check basic updates - assert_eq!(writer.last_block_number().unwrap(), block.number()); - assert_eq!(writer.latest_journal_hash().unwrap(), journal_hash); - assert_eq!(writer.get_journal_hash(block.number()).unwrap(), Some(journal_hash)); + assert_eq!(reader.last_block_number().unwrap(), block.number()); + assert_eq!(reader.latest_journal_hash().unwrap(), journal_hash); + assert_eq!(reader.get_journal_hash(block.number()).unwrap(), Some(journal_hash)); // This tests resolving `BlockId::Latest` - assert_eq!(writer.best_block_number().unwrap(), block.number()); + assert_eq!(reader.best_block_number().unwrap(), block.number()); // Check that the block can be loaded back - let loaded_block = writer + let loaded_block = reader .recovered_block_range(block.number()..=block.number()) .unwrap() .first() @@ -77,6 +78,6 @@ fn test_insert_signet_block() { assert_eq!(loaded_block.body().transactions.len(), block.block.body.transactions.len()); // Check that the ZenithHeader can be loaded back - let loaded_header = writer.get_signet_header(block.number()).unwrap(); + let loaded_header = reader.get_signet_header(block.number()).unwrap(); assert_eq!(loaded_header, header); } diff --git a/crates/node/src/node.rs b/crates/node/src/node.rs index 67934e7..2a9fc8b 100644 --- a/crates/node/src/node.rs +++ b/crates/node/src/node.rs @@ -660,10 +660,7 @@ where let mut reverted = None; self.ru_provider.provider_rw()?.update(|writer| { - reverted = Some(writer.ru_take_blocks_and_execution_above( - target, - reth::providers::StorageLocation::Both, - )?); + reverted = Some(writer.ru_take_blocks_and_execution_above(target)?); Ok(()) })?;