Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 38 additions & 37 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ members = ["crates/*"]
resolver = "2"

[workspace.package]
version = "0.11.4"
version = "0.14.0"
edition = "2024"
rust-version = "1.88"
authors = ["init4"]
Expand Down Expand Up @@ -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.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.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.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" }

# trevm
trevm = { version = "0.29.0", features = ["full_env_cfg"] }
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 = [
Expand All @@ -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.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"
Expand Down Expand Up @@ -132,6 +132,7 @@ tempfile = "3.17.0"
# 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"}
Expand Down
114 changes: 114 additions & 0 deletions crates/block-processor/src/alias.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
use alloy::{
consensus::constants::KECCAK_EMPTY,
primitives::{Address, map::HashSet},
};
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 {
/// Returns true if the given address is an alias.
fn should_alias(&self, address: Address) -> eyre::Result<bool>;
}

/// 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<dyn StateProvider> {
fn should_alias(&self, address: Address) -> eyre::Result<bool> {
// 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")?;

// If not a 7702 delegation contract, alias it.
Ok(!code.is_eip7702())
}
}

impl AliasOracle for HashSet<Address> {
fn should_alias(&self, address: Address) -> eyre::Result<bool> {
Ok(self.contains(&address))
}
}

/// Factory trait to create new [`AliasOracle`] instances.
///
/// The default implementation on `Box<dyn StateProviderFactory>` 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<Address>`] allows specifying a fixed set of
/// addresses to be aliased.
pub trait AliasOracleFactory: Send + Sync + 'static {
/// The [`AliasOracle`] type.
type Oracle: AliasOracle;

/// Create a new [`AliasOracle`].
fn create(&self) -> eyre::Result<Self::Oracle>;
}

impl AliasOracleFactory for Box<dyn StateProviderFactory> {
type Oracle = Box<dyn StateProvider>;

fn create(&self) -> eyre::Result<Self::Oracle> {
// 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)
}
}

/// This implementation is primarily for testing purposes.
impl AliasOracleFactory for HashSet<Address> {
type Oracle = HashSet<Address>;

fn create(&self) -> eyre::Result<Self::Oracle> {
Ok(self.clone())
}
}

impl<T> AliasOracleFactory for Mutex<T>
where
T: AliasOracleFactory,
{
type Oracle = T::Oracle;

fn create(&self) -> eyre::Result<Self::Oracle> {
let guard =
self.lock().map_err(|_| eyre::eyre!("failed to lock AliasOracleFactory mutex"))?;
guard.create()
}
}

impl<T> AliasOracleFactory for Arc<T>
where
T: AliasOracleFactory,
{
type Oracle = T::Oracle;

fn create(&self) -> eyre::Result<Self::Oracle> {
self.as_ref().create()
}
}
6 changes: 6 additions & 0 deletions crates/block-processor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@

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;

Expand Down
44 changes: 44 additions & 0 deletions crates/block-processor/src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
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_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
/// 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
| SpecId::AMSTERDAM => {}
}
}
Loading
Loading