Skip to content
Closed
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
8 changes: 5 additions & 3 deletions crates/block-processor/src/alias.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
use alloy::primitives::{Address, map::HashSet};
use core::future::Future;
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>;
fn should_alias(&self, address: Address) -> impl Future<Output = eyre::Result<bool>> + Send;
}

impl AliasOracle for HashSet<Address> {
fn should_alias(&self, address: Address) -> eyre::Result<bool> {
Ok(self.contains(&address))
fn should_alias(&self, address: Address) -> impl Future<Output = eyre::Result<bool>> + Send {
let result = Ok(self.contains(&address));
async move { result }
}
}

Expand Down
6 changes: 3 additions & 3 deletions crates/block-processor/src/v1/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ where
}

/// Check if the given address should be aliased.
fn should_alias(&self, address: Address) -> eyre::Result<bool> {
self.alias_oracle.create()?.should_alias(address)
async fn should_alias(&self, address: Address) -> eyre::Result<bool> {
self.alias_oracle.create()?.should_alias(address).await
}

/// Process a single extracted block, returning an [`ExecutedBlock`].
Expand Down Expand Up @@ -189,7 +189,7 @@ where
let mut to_alias: HashSet<Address> = Default::default();
for transact in block_extracts.transacts() {
let addr = transact.host_sender();
if !to_alias.contains(&addr) && self.should_alias(addr)? {
if !to_alias.contains(&addr) && self.should_alias(addr).await? {
to_alias.insert(addr);
}
}
Expand Down
45 changes: 24 additions & 21 deletions crates/host-reth/src/alias.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use alloy::{consensus::constants::KECCAK_EMPTY, primitives::Address};
use core::fmt;
use core::{fmt, future::Future};
use eyre::OptionExt;
use reth::providers::{StateProviderBox, StateProviderFactory};
use signet_block_processor::{AliasOracle, AliasOracleFactory};
Expand All @@ -17,27 +17,30 @@ impl fmt::Debug for RethAliasOracle {
}

impl AliasOracle for RethAliasOracle {
fn should_alias(&self, address: Address) -> eyre::Result<bool> {
// No account at this address.
let Some(acct) = self.0.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
.0
.bytecode_by_hash(&bch)?
.ok_or_eyre("code not found. This indicates a corrupted database")?;
fn should_alias(&self, address: Address) -> impl Future<Output = eyre::Result<bool>> + Send {
let result = (|| {
// No account at this address.
let Some(acct) = self.0.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
.0
.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())
// If not a 7702 delegation contract, alias it.
Ok(!code.is_eip7702())
})();
async move { result }
}
}

Expand Down
139 changes: 139 additions & 0 deletions docs/superpowers/plans/2026-03-13-async-alias-oracle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# Async AliasOracle Implementation Plan

> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Make `AliasOracle::should_alias` async using RPITIT to support future async implementations.

**Architecture:** Change the `AliasOracle` trait's `should_alias` method to return `impl Future<Output = eyre::Result<bool>> + Send`. Existing sync implementations wrap their bodies in `async move { ... }`. The single call site in `processor.rs` adds `.await`.

**Tech Stack:** Rust RPITIT (stable since 1.75), `core::future::Future`

---

## Chunk 1: Implementation

### Task 1: Update all AliasOracle impls and call site

All changes are made together in a single commit so no intermediate state breaks compilation.

**Files:**
- Modify: `crates/block-processor/src/alias.rs:1-14`
- Modify: `crates/host-reth/src/alias.rs:1-42`
- Modify: `crates/block-processor/src/v1/processor.rs:106-109,188-195`

- [ ] **Step 1: Update the trait definition and HashSet impl**

In `crates/block-processor/src/alias.rs`, add `Future` import and make `should_alias` return an async future:

```rust
use alloy::primitives::{Address, map::HashSet};
use core::future::Future;
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) -> impl Future<Output = eyre::Result<bool>> + Send;
}

impl AliasOracle for HashSet<Address> {
fn should_alias(&self, address: Address) -> impl Future<Output = eyre::Result<bool>> + Send {
let result = Ok(self.contains(&address));
async move { result }
}
}
```

Note: the `HashSet` impl computes the result synchronously _before_ the async block, so `&self` is not captured across the await point. This avoids requiring `Self: Sync`.

- [ ] **Step 2: Update RethAliasOracle impl**

In `crates/host-reth/src/alias.rs`, add `use core::future::Future;` to imports, then change the impl:

```rust
impl AliasOracle for RethAliasOracle {
fn should_alias(&self, address: Address) -> impl Future<Output = eyre::Result<bool>> + Send {
// Compute synchronously, then wrap in async.
let result = (|| {
// No account at this address.
let Some(acct) = self.0.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
.0
.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())
})();
async move { result }
}
}
```

- [ ] **Step 3: Update processor call site**

In `crates/block-processor/src/v1/processor.rs`, update the helper method (line 106-109):

```rust
/// Check if the given address should be aliased.
async fn should_alias(&self, address: Address) -> eyre::Result<bool> {
self.alias_oracle.create()?.should_alias(address).await
}
```

Update the loop in `run_evm` (line 192):

```rust
if !to_alias.contains(&addr) && self.should_alias(addr).await? {
```

- [ ] **Step 4: Format**

Run: `cargo +nightly fmt`

- [ ] **Step 5: Lint all affected crates**

Run: `cargo clippy -p signet-block-processor --all-features --all-targets`
Run: `cargo clippy -p signet-host-reth --all-features --all-targets`
Expected: PASS

- [ ] **Step 6: Run tests**

Run: `cargo t -p signet-block-processor`
Run: `cargo t -p signet-host-reth`
Expected: PASS

- [ ] **Step 7: Commit**

```bash
git add crates/block-processor/src/alias.rs crates/host-reth/src/alias.rs crates/block-processor/src/v1/processor.rs
git commit -m "refactor: make AliasOracle::should_alias async via RPITIT"
```

### Task 2: Full workspace validation

- [ ] **Step 1: Lint downstream crates**

Run: `cargo clippy -p signet-node --all-features --all-targets`
Run: `cargo clippy -p signet-node-tests --all-features --all-targets`
Expected: PASS (bounds are on `AliasOracleFactory`, not `AliasOracle` directly)

- [ ] **Step 2: Run node-tests**

Run: `cargo t -p signet-node-tests`
Expected: PASS

- [ ] **Step 3: Final format check**

Run: `cargo +nightly fmt`
Loading