Skip to content

Commit acc8002

Browse files
authored
feat: alias addresses (#44)
* feat: alias addresses * feat: alias oracle * chore: bump to 0.13 off aliasing branch * fix: tests pass again * chore: remove state provider height * chore: remove block height arg and add test * fix: use revm spec consistently * chore: bump to compat signet-sdk * chore: bump reth and update everything
1 parent a6daf31 commit acc8002

File tree

27 files changed

+449
-636
lines changed

27 files changed

+449
-636
lines changed

Cargo.toml

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ members = ["crates/*"]
33
resolver = "2"
44

55
[workspace.package]
6-
version = "0.11.4"
6+
version = "0.14.0"
77
edition = "2024"
88
rust-version = "1.88"
99
authors = ["init4"]
@@ -34,34 +34,34 @@ debug = false
3434
incremental = false
3535

3636
[workspace.dependencies]
37-
signet-blobber = { version = "0.11", path = "crates/blobber" }
38-
signet-block-processor = { version = "0.11", path = "crates/block-processor" }
39-
signet-db = { version = "0.11", path = "crates/db" }
40-
signet-genesis = { version = "0.11", path = "crates/genesis" }
41-
signet-node = { version = "0.11", path = "crates/node" }
42-
signet-node-config = { version = "0.11", path = "crates/node-config" }
43-
signet-node-tests = { version = "0.11", path = "crates/node-tests" }
44-
signet-node-types = { version = "0.11", path = "crates/node-types" }
45-
signet-rpc = { version = "0.11", path = "crates/rpc" }
46-
37+
signet-blobber = { version = "0.14", path = "crates/blobber" }
38+
signet-block-processor = { version = "0.14", path = "crates/block-processor" }
39+
signet-db = { version = "0.14", path = "crates/db" }
40+
signet-genesis = { version = "0.14", path = "crates/genesis" }
41+
signet-node = { version = "0.14", path = "crates/node" }
42+
signet-node-config = { version = "0.14", path = "crates/node-config" }
43+
signet-node-tests = { version = "0.14", path = "crates/node-tests" }
44+
signet-node-types = { version = "0.14", path = "crates/node-types" }
45+
signet-rpc = { version = "0.14", path = "crates/rpc" }
4746

4847
init4-bin-base = { version = "0.13.1", features = ["alloy"] }
4948

50-
signet-bundle = "0.11.1"
51-
signet-constants = "0.11.1"
52-
signet-evm = "0.11.1"
53-
signet-extract = "0.11.1"
54-
signet-test-utils = "0.11.1"
55-
signet-tx-cache = "0.11.1"
56-
signet-types = "0.11.1"
57-
signet-zenith = "0.11.1"
58-
signet-journal = "0.11.1"
49+
signet-bundle = "0.14"
50+
signet-constants = "0.14"
51+
signet-evm = "0.14"
52+
signet-extract = "0.14"
53+
signet-test-utils = "0.14"
54+
signet-tx-cache = "0.14"
55+
signet-types = "0.14"
56+
signet-zenith = "0.14"
57+
signet-journal = "0.14"
5958

6059
# ajj
6160
ajj = { version = "0.3.4" }
6261

6362
# trevm
64-
trevm = { version = "0.29.0", features = ["full_env_cfg"] }
63+
trevm = { version = "0.31.0", features = ["full_env_cfg"] }
64+
revm-inspectors = "0.32.0" # should be 1 more than trevm version, usually
6565

6666
# Alloy periphery crates
6767
alloy = { version = "1.0.35", features = [
@@ -74,22 +74,22 @@ alloy = { version = "1.0.35", features = [
7474
alloy-contract = { version = "1.0.35", features = ["pubsub"] }
7575

7676
# Reth
77-
reth = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" }
78-
reth-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" }
79-
reth-chainspec = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" }
80-
reth-db = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" }
81-
reth-db-common = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" }
82-
reth-eth-wire-types = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" }
83-
reth-evm-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" }
84-
reth-exex = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" }
85-
reth-exex-test-utils = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" }
86-
reth-network-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" }
87-
reth-network-peers = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" }
88-
reth-node-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" }
89-
reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" }
90-
reth-prune-types = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" }
91-
reth-rpc-eth-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" }
92-
reth-transaction-pool = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.1" }
77+
reth = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" }
78+
reth-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" }
79+
reth-chainspec = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" }
80+
reth-db = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" }
81+
reth-db-common = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" }
82+
reth-eth-wire-types = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" }
83+
reth-evm-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" }
84+
reth-exex = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" }
85+
reth-exex-test-utils = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" }
86+
reth-network-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" }
87+
reth-network-peers = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" }
88+
reth-node-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" }
89+
reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" }
90+
reth-prune-types = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" }
91+
reth-rpc-eth-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" }
92+
reth-transaction-pool = { git = "https://github.com/paradigmxyz/reth", tag = "v1.9.0" }
9393

9494
# Foundry periphery
9595
foundry-blob-explorers = "0.17"
@@ -132,6 +132,7 @@ tempfile = "3.17.0"
132132
# signet-constants = { path = "../sdk/crates/constants"}
133133
# signet-evm = { path = "../sdk/crates/evm"}
134134
# signet-extract = { path = "../sdk/crates/extract"}
135+
# signet-journal = { path = "../sdk/crates/journal"}
135136
# signet-test-utils = { path = "../sdk/crates/test-utils"}
136137
# signet-tx-cache = { path = "../sdk/crates/tx-cache"}
137138
# signet-types = { path = "../sdk/crates/types"}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
use alloy::{
2+
consensus::constants::KECCAK_EMPTY,
3+
primitives::{Address, map::HashSet},
4+
};
5+
use eyre::OptionExt;
6+
use reth::providers::{StateProvider, StateProviderFactory};
7+
use std::sync::{Arc, Mutex};
8+
9+
/// Simple trait to allow checking if an address should be aliased.
10+
pub trait AliasOracle {
11+
/// Returns true if the given address is an alias.
12+
fn should_alias(&self, address: Address) -> eyre::Result<bool>;
13+
}
14+
15+
/// Default implementation of [`AliasOracle`] for any type implementing
16+
/// [`StateProvider`]. This implementation checks if the address has bytecode
17+
/// associated with it, and if so, whether that bytecode matches the pattern
18+
/// for a 7702 delegation contract. If it is a delegation contract, it is not
19+
/// aliased; otherwise, it is aliased.
20+
impl AliasOracle for Box<dyn StateProvider> {
21+
fn should_alias(&self, address: Address) -> eyre::Result<bool> {
22+
// No account at this address.
23+
let Some(acct) = self.basic_account(&address)? else { return Ok(false) };
24+
// Get the bytecode hash for this account.
25+
let bch = match acct.bytecode_hash {
26+
Some(hash) => hash,
27+
// No bytecode hash; not a contract.
28+
None => return Ok(false),
29+
};
30+
// No code at this address.
31+
if bch == KECCAK_EMPTY {
32+
return Ok(false);
33+
}
34+
// Fetch the code associated with this bytecode hash.
35+
let code = self
36+
.bytecode_by_hash(&bch)?
37+
.ok_or_eyre("code not found. This indicates a corrupted database")?;
38+
39+
// If not a 7702 delegation contract, alias it.
40+
Ok(!code.is_eip7702())
41+
}
42+
}
43+
44+
impl AliasOracle for HashSet<Address> {
45+
fn should_alias(&self, address: Address) -> eyre::Result<bool> {
46+
Ok(self.contains(&address))
47+
}
48+
}
49+
50+
/// Factory trait to create new [`AliasOracle`] instances.
51+
///
52+
/// The default implementation on `Box<dyn StateProviderFactory>` creates
53+
/// [`AliasOracle`] instances backed by the state provider for a given block
54+
/// height. It will error if that state provider cannot be obtained.
55+
///
56+
/// This trait is primarily intended to allow injecting test implementations
57+
/// of [`AliasOracle`] into the Signet Node for testing purposes. The test
58+
/// implementation on [`HashSet<Address>`] allows specifying a fixed set of
59+
/// addresses to be aliased.
60+
pub trait AliasOracleFactory: Send + Sync + 'static {
61+
/// The [`AliasOracle`] type.
62+
type Oracle: AliasOracle;
63+
64+
/// Create a new [`AliasOracle`].
65+
fn create(&self) -> eyre::Result<Self::Oracle>;
66+
}
67+
68+
impl AliasOracleFactory for Box<dyn StateProviderFactory> {
69+
type Oracle = Box<dyn StateProvider>;
70+
71+
fn create(&self) -> eyre::Result<Self::Oracle> {
72+
// NB: This becomes a problem if anyone ever birthday attacks a
73+
// contract/EOA pair (c.f. EIP-3607). In practice this is unlikely to
74+
// happen for the foreseeable future, and if it does we can revisit
75+
// this decision.
76+
// We considered taking the host height as an argument to this method,
77+
// but this would require all nodes to be archive nodes in order to
78+
// sync, which is less than ideal
79+
self.state_by_block_number_or_tag(alloy::eips::BlockNumberOrTag::Latest).map_err(Into::into)
80+
}
81+
}
82+
83+
/// This implementation is primarily for testing purposes.
84+
impl AliasOracleFactory for HashSet<Address> {
85+
type Oracle = HashSet<Address>;
86+
87+
fn create(&self) -> eyre::Result<Self::Oracle> {
88+
Ok(self.clone())
89+
}
90+
}
91+
92+
impl<T> AliasOracleFactory for Mutex<T>
93+
where
94+
T: AliasOracleFactory,
95+
{
96+
type Oracle = T::Oracle;
97+
98+
fn create(&self) -> eyre::Result<Self::Oracle> {
99+
let guard =
100+
self.lock().map_err(|_| eyre::eyre!("failed to lock AliasOracleFactory mutex"))?;
101+
guard.create()
102+
}
103+
}
104+
105+
impl<T> AliasOracleFactory for Arc<T>
106+
where
107+
T: AliasOracleFactory,
108+
{
109+
type Oracle = T::Oracle;
110+
111+
fn create(&self) -> eyre::Result<Self::Oracle> {
112+
self.as_ref().create()
113+
}
114+
}

crates/block-processor/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@
1313

1414
pub(crate) mod metrics;
1515

16+
mod alias;
17+
pub use alias::{AliasOracle, AliasOracleFactory};
18+
19+
mod utils;
20+
pub use utils::revm_spec;
21+
1622
mod v1;
1723
pub use v1::SignetBlockProcessor as SignetBlockProcessorV1;
1824

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use reth::revm::primitives::hardfork::SpecId;
2+
use reth_chainspec::EthereumHardforks;
3+
4+
/// Equivalent to [`reth_evm_ethereum::revm_spec`], however, always starts at
5+
/// [`SpecId::PRAGUE`] and transitions to [`SpecId::OSAKA`].
6+
pub fn revm_spec(chain_spec: &reth::chainspec::ChainSpec, timestamp: u64) -> SpecId {
7+
if chain_spec.is_amsterdam_active_at_timestamp(timestamp) {
8+
SpecId::AMSTERDAM
9+
} else if chain_spec.is_osaka_active_at_timestamp(timestamp) {
10+
SpecId::OSAKA
11+
} else {
12+
SpecId::PRAGUE
13+
}
14+
}
15+
16+
/// This is simply a compile-time assertion to ensure that all SpecIds are
17+
/// covered in the match. When this fails to compile, it indicates that a new
18+
/// hardfork has been added and [`revm_spec`] needs to be updated.
19+
#[allow(dead_code)]
20+
const fn assert_in_range(spec_id: SpecId) {
21+
match spec_id {
22+
SpecId::FRONTIER
23+
| SpecId::FRONTIER_THAWING
24+
| SpecId::HOMESTEAD
25+
| SpecId::DAO_FORK
26+
| SpecId::TANGERINE
27+
| SpecId::SPURIOUS_DRAGON
28+
| SpecId::BYZANTIUM
29+
| SpecId::CONSTANTINOPLE
30+
| SpecId::PETERSBURG
31+
| SpecId::ISTANBUL
32+
| SpecId::MUIR_GLACIER
33+
| SpecId::BERLIN
34+
| SpecId::LONDON
35+
| SpecId::ARROW_GLACIER
36+
| SpecId::GRAY_GLACIER
37+
| SpecId::MERGE
38+
| SpecId::SHANGHAI
39+
| SpecId::CANCUN
40+
| SpecId::PRAGUE
41+
| SpecId::OSAKA
42+
| SpecId::AMSTERDAM => {}
43+
}
44+
}

0 commit comments

Comments
 (0)