Skip to content
Open
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
1 change: 1 addition & 0 deletions crates/block-processor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ alloy.workspace = true

eyre.workspace = true
metrics.workspace = true
thiserror.workspace = true
tracing.workspace = true
34 changes: 26 additions & 8 deletions crates/block-processor/src/alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,33 @@ use alloy::primitives::{Address, map::HashSet};
use core::future::{self, Future};
use std::sync::{Arc, Mutex};

/// Error type for [`AliasOracle`] and [`AliasOracleFactory`] operations.
///
/// Implementation-specific errors are wrapped in the [`Internal`] variant.
///
/// [`Internal`]: AliasError::Internal
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum AliasError {
/// An implementation-specific error.
#[error(transparent)]
Internal(Box<dyn core::error::Error + Send + Sync>),
}

/// 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) -> impl Future<Output = eyre::Result<bool>> + Send;
fn should_alias(
&self,
address: Address,
) -> impl Future<Output = Result<bool, AliasError>> + Send;
}

impl AliasOracle for HashSet<Address> {
fn should_alias(&self, address: Address) -> impl Future<Output = eyre::Result<bool>> + Send {
fn should_alias(
&self,
address: Address,
) -> impl Future<Output = Result<bool, AliasError>> + Send {
future::ready(Ok(self.contains(&address)))
}
}
Expand All @@ -28,14 +47,14 @@ pub trait AliasOracleFactory: Send + Sync + 'static {
type Oracle: AliasOracle;

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

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

fn create(&self) -> eyre::Result<Self::Oracle> {
fn create(&self) -> Result<Self::Oracle, AliasError> {
Ok(self.clone())
}
}
Expand All @@ -46,9 +65,8 @@ where
{
type Oracle = T::Oracle;

fn create(&self) -> eyre::Result<Self::Oracle> {
let guard =
self.lock().map_err(|_| eyre::eyre!("failed to lock AliasOracleFactory mutex"))?;
fn create(&self) -> Result<Self::Oracle, AliasError> {
let guard = self.lock().map_err(|e| AliasError::Internal(e.to_string().into()))?;
guard.create()
}
}
Expand All @@ -59,7 +77,7 @@ where
{
type Oracle = T::Oracle;

fn create(&self) -> eyre::Result<Self::Oracle> {
fn create(&self) -> Result<Self::Oracle, AliasError> {
self.as_ref().create()
}
}
2 changes: 1 addition & 1 deletion crates/block-processor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
pub(crate) mod metrics;

mod alias;
pub use alias::{AliasOracle, AliasOracleFactory};
pub use alias::{AliasError, AliasOracle, AliasOracleFactory};

mod v1;
pub use v1::SignetBlockProcessor as SignetBlockProcessorV1;
1 change: 0 additions & 1 deletion crates/host-reth/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ reth-exex.workspace = true
reth-node-api.workspace = true
reth-stages-types.workspace = true

eyre.workspace = true
futures-util.workspace = true
thiserror.workspace = true
tokio.workspace = true
Expand Down
27 changes: 18 additions & 9 deletions crates/host-reth/src/alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ use core::{
fmt,
future::{self, Future},
};
use eyre::OptionExt;
use reth::providers::{StateProviderBox, StateProviderFactory};
use signet_block_processor::{AliasOracle, AliasOracleFactory};
use signet_block_processor::{AliasError, AliasOracle, AliasOracleFactory};

/// An [`AliasOracle`] backed by a reth [`StateProviderBox`].
///
Expand All @@ -21,8 +20,12 @@ impl fmt::Debug for RethAliasOracle {

impl RethAliasOracle {
/// Synchronously check whether the given address should be aliased.
fn check_alias(&self, address: Address) -> eyre::Result<bool> {
let Some(acct) = self.0.basic_account(&address)? else { return Ok(false) };
fn check_alias(&self, address: Address) -> Result<bool, AliasError> {
let Some(acct) =
self.0.basic_account(&address).map_err(|e| AliasError::Internal(Box::new(e)))?
else {
return Ok(false);
};
// Get the bytecode hash for this account.
let bch = match acct.bytecode_hash {
Some(hash) => hash,
Expand All @@ -36,16 +39,22 @@ impl RethAliasOracle {
// Fetch the code associated with this bytecode hash.
let code = self
.0
.bytecode_by_hash(&bch)?
.ok_or_eyre("code not found. This indicates a corrupted database")?;
.bytecode_by_hash(&bch)
.map_err(|e| AliasError::Internal(Box::new(e)))?
.ok_or_else(|| {
AliasError::Internal("code not found. This indicates a corrupted database".into())
})?;

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

impl AliasOracle for RethAliasOracle {
fn should_alias(&self, address: Address) -> impl Future<Output = eyre::Result<bool>> + Send {
fn should_alias(
&self,
address: Address,
) -> impl Future<Output = Result<bool, AliasError>> + Send {
future::ready(self.check_alias(address))
}
}
Expand All @@ -72,7 +81,7 @@ impl RethAliasOracleFactory {
impl AliasOracleFactory for RethAliasOracleFactory {
type Oracle = RethAliasOracle;

fn create(&self) -> eyre::Result<Self::Oracle> {
fn create(&self) -> Result<Self::Oracle, AliasError> {
// We use `Latest` rather than a pinned host height because pinning
// would require every node to be an archive node, which is impractical.
//
Expand All @@ -85,6 +94,6 @@ impl AliasOracleFactory for RethAliasOracleFactory {
self.0
.state_by_block_number_or_tag(alloy::eips::BlockNumberOrTag::Latest)
.map(RethAliasOracle)
.map_err(Into::into)
.map_err(|e| AliasError::Internal(Box::new(e)))
}
}
1 change: 0 additions & 1 deletion crates/host-rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ signet-extract.workspace = true
signet-types.workspace = true

alloy.workspace = true
eyre.workspace = true
init4-bin-base.workspace = true
futures-util.workspace = true
metrics.workspace = true
Expand Down
12 changes: 8 additions & 4 deletions crates/host-rpc/src/alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use alloy::{
primitives::{Address, map::HashSet},
providers::Provider,
};
use signet_block_processor::{AliasOracle, AliasOracleFactory};
use signet_block_processor::{AliasError, AliasOracle, AliasOracleFactory};
use std::sync::{Arc, RwLock};
use tracing::{debug, instrument};

Expand Down Expand Up @@ -60,7 +60,7 @@ fn should_alias_bytecode(code: &[u8]) -> bool {

impl<P: Provider + Clone + 'static> AliasOracle for RpcAliasOracle<P> {
#[instrument(skip(self), fields(%address))]
async fn should_alias(&self, address: Address) -> eyre::Result<bool> {
async fn should_alias(&self, address: Address) -> Result<bool, AliasError> {
// NOTE: `std::sync::RwLock` is safe here because guards are always
// dropped before the `.await` point. Do not hold a guard across the
// `get_code_at` call — it will deadlock on single-threaded runtimes.
Expand All @@ -71,7 +71,11 @@ impl<P: Provider + Clone + 'static> AliasOracle for RpcAliasOracle<P> {
return Ok(true);
}

let code = self.provider.get_code_at(address).await?;
let code = self
.provider
.get_code_at(address)
.await
.map_err(|e| AliasError::Internal(Box::new(e)))?;
let alias = should_alias_bytecode(&code);
debug!(code_len = code.len(), alias, "resolved");

Expand All @@ -86,7 +90,7 @@ impl<P: Provider + Clone + 'static> AliasOracle for RpcAliasOracle<P> {
impl<P: Provider + Clone + 'static> AliasOracleFactory for RpcAliasOracle<P> {
type Oracle = Self;

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