Skip to content

Commit

Permalink
chore: abstract away hashbrown (#7395)
Browse files Browse the repository at this point in the history
* chore: abstract away hashbrown

* deps

* fix

* log

* fix: use indexset

* test

* test
  • Loading branch information
DaniPopes authored Mar 19, 2024
1 parent ffed0de commit a527c1c
Show file tree
Hide file tree
Showing 19 changed files with 76 additions and 70 deletions.
5 changes: 2 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 3 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ foundry-compilers = { version = "0.3.13", default-features = false }

## revm
# no default features to avoid c-kzg
revm = { version = "7.1", default-features = false }
revm-primitives = { version = "3", default-features = false }
revm = { version = "7.1", default-features = false, features = ["std"] }
revm-primitives = { version = "3", default-features = false, features = ["std"] }
revm-inspectors = { git = "https://github.com/paradigmxyz/evm-inspectors", rev = "ba0b6ab", features = [
"serde",
] }
Expand Down Expand Up @@ -207,14 +207,9 @@ toml = "0.8"
tracing = "0.1"
tracing-subscriber = "0.3"
vergen = { version = "8", default-features = false }
indexmap = "2.2"

axum = "0.6"
hyper = "0.14"
tower = "0.4"
tower-http = "0.4"

# [patch.crates-io]
# revm = { path = "../../danipopes/revm/crates/revm" }
# revm-interpreter = { path = "../../danipopes/revm/crates/interpreter" }
# revm-primitives = { path = "../../danipopes/revm/crates/primitives" }
# revm-precompile = { path = "../../danipopes/revm/crates/precompile" }
3 changes: 1 addition & 2 deletions crates/anvil/src/eth/backend/cheats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

use alloy_primitives::{Address, Signature};
use anvil_core::eth::transaction::impersonated_signature;
use foundry_evm::hashbrown::HashSet;
use parking_lot::RwLock;
use std::sync::Arc;
use std::{collections::HashSet, sync::Arc};

/// Manages user modifications that may affect the node's behavior
///
Expand Down
4 changes: 2 additions & 2 deletions crates/anvil/src/eth/backend/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ use foundry_common::errors::FsPathError;
use foundry_evm::{
backend::{DatabaseError, DatabaseResult, MemDb, RevertSnapshotAction, StateSnapshot},
fork::BlockchainDb,
hashbrown::HashMap,
revm::{
db::{CacheDB, DatabaseRef, DbAccount},
primitives::{BlockEnv, Bytecode, KECCAK_EMPTY},
primitives::{BlockEnv, Bytecode, HashMap, KECCAK_EMPTY},
Database, DatabaseCommit,
},
};
Expand Down Expand Up @@ -225,6 +224,7 @@ impl<T: DatabaseRef<Error = DatabaseError>> MaybeHashDatabase for CacheDB<T> {
fn maybe_as_hash_db(&self) -> Option<(AsHashDB, B256)> {
Some(trie_hash_db(&self.accounts))
}

fn clear_into_snapshot(&mut self) -> StateSnapshot {
let db_accounts = std::mem::take(&mut self.accounts);
let mut accounts = HashMap::new();
Expand Down
13 changes: 6 additions & 7 deletions crates/anvil/src/eth/backend/mem/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,16 @@ use alloy_rpc_types::state::StateOverride;
use anvil_core::eth::trie::RefSecTrieDBMut;
use foundry_evm::{
backend::DatabaseError,
hashbrown::HashMap as Map,
revm::{
db::{CacheDB, DatabaseRef, DbAccount},
primitives::{AccountInfo, Bytecode},
primitives::{AccountInfo, Bytecode, HashMap},
},
};
use memory_db::HashKey;
use trie_db::TrieMut;

/// Returns storage trie of an account as `HashDB`
pub fn storage_trie_db(storage: &Map<U256, U256>) -> (AsHashDB, B256) {
pub fn storage_trie_db(storage: &HashMap<U256, U256>) -> (AsHashDB, B256) {
// Populate DB with full trie from entries.
let (db, root) = {
let mut db = <memory_db::MemoryDB<_, HashKey<_>, _>>::default();
Expand All @@ -38,7 +37,7 @@ pub fn storage_trie_db(storage: &Map<U256, U256>) -> (AsHashDB, B256) {
}

/// Returns the account data as `HashDB`
pub fn trie_hash_db(accounts: &Map<Address, DbAccount>) -> (AsHashDB, B256) {
pub fn trie_hash_db(accounts: &HashMap<Address, DbAccount>) -> (AsHashDB, B256) {
let accounts = trie_accounts(accounts);

// Populate DB with full trie from entries.
Expand All @@ -58,7 +57,7 @@ pub fn trie_hash_db(accounts: &Map<Address, DbAccount>) -> (AsHashDB, B256) {
}

/// Returns all RLP-encoded Accounts
pub fn trie_accounts(accounts: &Map<Address, DbAccount>) -> Vec<(Address, Bytes)> {
pub fn trie_accounts(accounts: &HashMap<Address, DbAccount>) -> Vec<(Address, Bytes)> {
accounts
.iter()
.map(|(address, account)| {
Expand All @@ -68,12 +67,12 @@ pub fn trie_accounts(accounts: &Map<Address, DbAccount>) -> Vec<(Address, Bytes)
.collect()
}

pub fn state_merkle_trie_root(accounts: &Map<Address, DbAccount>) -> B256 {
pub fn state_merkle_trie_root(accounts: &HashMap<Address, DbAccount>) -> B256 {
trie_hash_db(accounts).1
}

/// Returns the RLP for this account.
pub fn trie_account_rlp(info: &AccountInfo, storage: &Map<U256, U256>) -> Bytes {
pub fn trie_account_rlp(info: &AccountInfo, storage: &HashMap<U256, U256>) -> Bytes {
let mut out: Vec<u8> = Vec::new();
let list: [&dyn Encodable; 4] =
[&info.nonce, &info.balance, &storage_trie_db(storage).1, &info.code_hash];
Expand Down
2 changes: 1 addition & 1 deletion crates/config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ foundry-compilers = { workspace = true, features = ["svm-solc"] }

alloy-chains = { workspace = true, features = ["serde"] }
alloy-primitives = { workspace = true, features = ["serde"] }
revm-primitives = { workspace = true, default-features = false, features = ["std"] }
revm-primitives.workspace = true

solang-parser.workspace = true

Expand Down
8 changes: 4 additions & 4 deletions crates/evm/core/src/backend/snapshot.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use alloy_primitives::{Address, B256, U256};
use revm::{
primitives::{AccountInfo, Env, HashMap as Map},
primitives::{AccountInfo, Env, HashMap},
JournaledState,
};
use serde::{Deserialize, Serialize};

/// A minimal abstraction of a state at a certain point in time
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct StateSnapshot {
pub accounts: Map<Address, AccountInfo>,
pub storage: Map<Address, Map<U256, U256>>,
pub block_hashes: Map<U256, B256>,
pub accounts: HashMap<Address, AccountInfo>,
pub storage: HashMap<Address, HashMap<U256, U256>>,
pub block_hashes: HashMap<U256, B256>,
}

/// Represents a snapshot taken during evm execution
Expand Down
8 changes: 3 additions & 5 deletions crates/evm/evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ alloy-dyn-abi = { workspace = true, features = ["arbitrary", "eip712"] }
alloy-json-abi.workspace = true
alloy-primitives = { workspace = true, features = ["serde", "getrandom", "arbitrary", "rlp"] }
alloy-sol-types.workspace = true
hashbrown = { version = "0.14", features = ["serde"] }
revm = { workspace = true, default-features = false, features = [
"std",
"serde",
Expand All @@ -36,14 +35,13 @@ revm = { workspace = true, default-features = false, features = [
] }
revm-inspectors.workspace = true

itertools.workspace = true

arrayvec.workspace = true
eyre = "0.6"
hex.workspace = true
itertools.workspace = true
parking_lot = "0.12"
proptest = "1"
rand.workspace = true
rayon = "1"
thiserror = "1"
tracing = "0.1"
rayon = "1"
rand.workspace = true
8 changes: 7 additions & 1 deletion crates/evm/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,10 @@ pub use foundry_evm_traces as traces;

// TODO: We should probably remove these, but it's a pretty big breaking change.
#[doc(hidden)]
pub use {hashbrown, revm};
pub use revm;

#[doc(hidden)]
#[deprecated = "use `{hash_map, hash_set, HashMap, HashSet}` in `std::collections` or `revm::primitives` instead"]
pub mod hashbrown {
pub use revm::primitives::{hash_map, hash_set, HashMap, HashSet};
}
3 changes: 2 additions & 1 deletion crates/evm/fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,12 @@ revm = { workspace = true, default-features = false, features = [
] }

eyre = "0.6"
hashbrown = { version = "0.14", features = ["serde"] }
itertools.workspace = true
parking_lot = "0.12"
proptest = "1"
rand.workspace = true
serde = "1"
thiserror = "1"
tracing = "0.1"
rustc-hash.workspace = true
indexmap.workspace = true
3 changes: 1 addition & 2 deletions crates/evm/fuzz/src/strategies/calldata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ use alloy_dyn_abi::JsonAbiExt;
use alloy_json_abi::Function;
use alloy_primitives::{Address, Bytes};
use foundry_config::FuzzDictionaryConfig;
use hashbrown::HashSet;
use proptest::prelude::Strategy;
use std::sync::Arc;
use std::{collections::HashSet, sync::Arc};

/// Clonable wrapper around [CalldataFuzzDictionary].
#[derive(Clone, Debug)]
Expand Down
18 changes: 11 additions & 7 deletions crates/evm/fuzz/src/strategies/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use alloy_primitives::{Address, Bytes, Log, B256, U256};
use foundry_common::contracts::{ContractsByAddress, ContractsByArtifact};
use foundry_config::FuzzDictionaryConfig;
use foundry_evm_core::utils::StateChangeset;
use hashbrown::HashSet;
use parking_lot::RwLock;
use proptest::prelude::{BoxedStrategy, Strategy};
use revm::{
Expand All @@ -16,6 +15,11 @@ use revm::{
};
use std::{fmt, sync::Arc};

// We're using `IndexSet` to have a stable element order when restoring persisted state, as well as
// for performance when iterating over the sets.
type FxIndexSet<T> =
indexmap::set::IndexSet<T, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;

/// A set of arbitrary 32 byte data from the VM used to generate values for the strategy.
///
/// Wrapped in a shareable container.
Expand All @@ -24,9 +28,9 @@ pub type EvmFuzzState = Arc<RwLock<FuzzDictionary>>;
#[derive(Default)]
pub struct FuzzDictionary {
/// Collected state values.
state_values: HashSet<[u8; 32]>,
state_values: FxIndexSet<[u8; 32]>,
/// Addresses that already had their PUSH bytes collected.
addresses: HashSet<Address>,
addresses: FxIndexSet<Address>,
}

impl fmt::Debug for FuzzDictionary {
Expand All @@ -40,22 +44,22 @@ impl fmt::Debug for FuzzDictionary {

impl FuzzDictionary {
#[inline]
pub fn values(&self) -> &HashSet<[u8; 32]> {
pub fn values(&self) -> &FxIndexSet<[u8; 32]> {
&self.state_values
}

#[inline]
pub fn values_mut(&mut self) -> &mut HashSet<[u8; 32]> {
pub fn values_mut(&mut self) -> &mut FxIndexSet<[u8; 32]> {
&mut self.state_values
}

#[inline]
pub fn addresses(&self) -> &HashSet<Address> {
pub fn addresses(&self) -> &FxIndexSet<Address> {
&self.addresses
}

#[inline]
pub fn addresses_mut(&mut self) -> &mut HashSet<Address> {
pub fn addresses_mut(&mut self) -> &mut FxIndexSet<Address> {
&mut self.addresses
}
}
Expand Down
1 change: 0 additions & 1 deletion crates/evm/traces/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ revm-inspectors.workspace = true

eyre = "0.6"
futures = "0.3"
hashbrown = "0.14"
hex.workspace = true
itertools.workspace = true
once_cell = "1"
Expand Down
7 changes: 5 additions & 2 deletions crates/evm/traces/src/identifier/signatures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ use foundry_common::{
fs,
selectors::{SelectorType, SignEthClient},
};
use hashbrown::HashSet;
use serde::{Deserialize, Serialize};
use std::{collections::BTreeMap, path::PathBuf, sync::Arc};
use std::{
collections::{BTreeMap, HashSet},
path::PathBuf,
sync::Arc,
};
use tokio::sync::RwLock;

pub type SingleSignaturesIdentifier = Arc<RwLock<SignaturesIdentifier>>;
Expand Down
9 changes: 4 additions & 5 deletions crates/forge/bin/cmd/remappings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ use clap::{Parser, ValueHint};
use eyre::Result;
use foundry_cli::utils::LoadConfig;
use foundry_config::impl_figment_convert_basic;
use foundry_evm::hashbrown::HashMap;
use std::path::PathBuf;
use std::{collections::BTreeMap, path::PathBuf};

/// CLI arguments for `forge remappings`.
#[derive(Clone, Debug, Parser)]
Expand All @@ -25,7 +24,7 @@ impl RemappingArgs {
let config = self.try_load_config_emit_warnings()?;

if self.pretty {
let mut groups = HashMap::<_, Vec<_>>::with_capacity(config.remappings.len());
let mut groups = BTreeMap::<_, Vec<_>>::new();
for remapping in config.remappings {
groups.entry(remapping.context.clone()).or_default().push(remapping);
}
Expand All @@ -36,14 +35,14 @@ impl RemappingArgs {
println!("Global:");
}

for mut remapping in remappings.into_iter() {
for mut remapping in remappings {
remapping.context = None; // avoid writing context twice
println!("- {remapping}");
}
println!();
}
} else {
for remapping in config.remappings.into_iter() {
for remapping in config.remappings {
println!("{remapping}");
}
}
Expand Down
6 changes: 4 additions & 2 deletions crates/forge/src/gas_report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@

use crate::{
constants::{CHEATCODE_ADDRESS, HARDHAT_CONSOLE_ADDRESS},
hashbrown::HashSet,
traces::{CallTraceArena, CallTraceDecoder, CallTraceNode, DecodedCallData},
};
use comfy_table::{presets::ASCII_MARKDOWN, *};
use foundry_common::{calc, TestFunctionExt};
use foundry_evm::traces::CallKind;
use serde::{Deserialize, Serialize};
use std::{collections::BTreeMap, fmt::Display};
use std::{
collections::{BTreeMap, HashSet},
fmt::Display,
};

/// Represents the gas report for a set of contracts.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
Expand Down
4 changes: 2 additions & 2 deletions crates/forge/tests/it/fuzz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,13 @@ async fn test_persist_fuzz_failure() {
};

// run several times and compare counterexamples calldata
for _ in 0..10 {
for i in 0..10 {
let new_calldata = match get_failure_result!() {
Some(CounterExample::Single(counterexample)) => counterexample.calldata,
_ => Bytes::new(),
};
// calldata should be the same with the initial one
assert_eq!(initial_calldata, new_calldata);
assert_eq!(initial_calldata, new_calldata, "run {i}");
}

// write new failure in different file
Expand Down
Loading

0 comments on commit a527c1c

Please sign in to comment.