Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: alloy migration #535

Merged
merged 1 commit into from
Aug 16, 2023
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
516 changes: 401 additions & 115 deletions Cargo.lock

Large diffs are not rendered by default.

7 changes: 2 additions & 5 deletions bins/revme/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,20 @@ version = "0.2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bytes = "1.4"
hash-db = "0.15"
hashbrown = "0.14"
hex = "0.4"
indicatif = "0.17"
plain_hasher = "0.2"
primitive-types = { version = "0.12", features = ["rlp", "serde"] }
revm = { path = "../../crates/revm", version = "3.3.0", default-features = false, features = [
"ethersdb",
"std",
"serde",
] }
rlp = { version = "0.5", default-features = false }
ruint = { version = "1.8.0", features = ["rlp", "serde"] }
alloy-rlp = { version = "0.3", default-features = false, features = ["arrayvec"] }
ruint = { version = "1.9.0", features = ["rlp", "serde"] }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to reexport it from alloy so the version and all other things are tied to it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ruint is already reexported so it can be removed, but rlp needs the "arrayvec" feature flag

serde = { version = "1.0", features = ["derive", "rc"] }
serde_json = { version = "1.0", features = ["preserve_order"] }
sha3 = { version = "0.10", default-features = false }
structopt = "0.3"
thiserror = "1.0"
triehash = "0.8"
Expand Down
29 changes: 9 additions & 20 deletions bins/revme/src/cli_env.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use std::str::FromStr;

use bytes::Bytes;
use revm::primitives::{Env, TransactTo, B160, U256};
use revm::primitives::{Address, Bytes, Env, TransactTo, U256};
use structopt::StructOpt;

#[derive(StructOpt, Clone, Debug)]
Expand Down Expand Up @@ -63,8 +60,8 @@ pub struct CliEnvBlock {
pub number: Option<u64>,
/// Coinbase or miner or address that created and signed the block.
/// Address where we are going to send gas spend
#[structopt(long = "env.block.coinbase", parse(try_from_str = parse_b160))]
pub coinbase: Option<B160>,
#[structopt(long = "env.block.coinbase")]
pub coinbase: Option<Address>,
#[structopt(long = "env.block.timestamp")]
pub timestamp: Option<u64>,
#[structopt(long = "env.block.difficulty")]
Expand All @@ -77,32 +74,24 @@ pub struct CliEnvBlock {
#[derive(StructOpt, Clone, Debug)]
pub struct CliEnvTx {
/// Caller or Author or tx signer
#[structopt(long = "env.tx.caller", parse(try_from_str = parse_b160))]
pub caller: Option<B160>,
#[structopt(long = "env.tx.caller")]
pub caller: Option<Address>,
#[structopt(long = "env.tx.gas_limit")]
pub tx_gas_limit: Option<u64>,
#[structopt(long = "env.tx.gas_price")]
pub gas_price: Option<u64>,
#[structopt(long = "env.tx.gas_priority_fee")]
pub gas_priority_fee: Option<u64>,
#[structopt(long = "env.tx.to", parse(try_from_str = parse_b160))]
pub transact_to: Option<B160>,
#[structopt(long = "env.tx.to")]
pub transact_to: Option<Address>,
#[structopt(long = "env.tx.value")]
pub value: Option<u64>,
#[structopt(long = "env.tx.data", parse(try_from_str = parse_hex))]
#[structopt(long = "env.tx.data")]
pub data: Option<Bytes>,
#[structopt(long = "env.tx.chain_id")]
pub chain_id: Option<u64>,
#[structopt(long = "env.tx.nonce")]
pub nonce: Option<u64>,
//#[structopt(long = "env.")]
//TODO pub access_list: Vec<(B160, Vec<U256>)>,
}

fn parse_hex(src: &str) -> Result<Bytes, hex::FromHexError> {
Ok(Bytes::from(hex::decode(src)?))
}

pub fn parse_b160(input: &str) -> Result<B160, <B160 as FromStr>::Err> {
B160::from_str(input)
//TODO pub access_list: Vec<(Address, Vec<U256>)>,
}
97 changes: 46 additions & 51 deletions bins/revme/src/statetest/merkle_trie.rs
Original file line number Diff line number Diff line change
@@ -1,79 +1,74 @@
use bytes::Bytes;
use alloy_rlp::{RlpEncodable, RlpMaxEncodedLen};
use hash_db::Hasher;
use plain_hasher::PlainHasher;
use primitive_types::{H160, H256};
use revm::{
db::PlainAccount,
primitives::{keccak256, Log, B160, B256, U256},
primitives::{keccak256, Address, Log, B256, U256},
};
use rlp::RlpStream;
use sha3::{Digest, Keccak256};
use triehash::sec_trie_root;

pub fn log_rlp_hash(logs: Vec<Log>) -> B256 {
//https://github.com/ethereum/go-ethereum/blob/356bbe343a30789e77bb38f25983c8f2f2bfbb47/cmd/evm/internal/t8ntool/execution.go#L255
let mut stream = RlpStream::new();
stream.begin_unbounded_list();
for log in logs {
stream.begin_list(3);
stream.append(&log.address.0.as_ref());
stream.begin_unbounded_list();
for topic in log.topics {
stream.append(&topic.0.as_ref());
}
stream.finalize_unbounded_list();
stream.append(&log.data);
}
stream.finalize_unbounded_list();
let out = stream.out().freeze();

pub fn log_rlp_hash(logs: &[Log]) -> B256 {
let mut out = Vec::with_capacity(alloy_rlp::list_length(logs));
alloy_rlp::encode_list(logs, &mut out);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, this is nice!

keccak256(&out)
}

pub fn state_merkle_trie_root<'a>(
accounts: impl IntoIterator<Item = (B160, &'a PlainAccount)>,
accounts: impl IntoIterator<Item = (Address, &'a PlainAccount)>,
) -> B256 {
let vec = accounts
.into_iter()
.map(|(address, info)| {
let acc_root = trie_account_rlp(info);
(H160::from(address.0), acc_root)
})
.collect();
trie_root(accounts.into_iter().map(|(address, acc)| {
(
address,
alloy_rlp::encode_fixed_size(&TrieAccount::new(acc)),
)
}))
}

trie_root(vec)
#[derive(RlpEncodable, RlpMaxEncodedLen)]
struct TrieAccount {
nonce: u64,
balance: U256,
root_hash: B256,
code_hash: B256,
}

/// Returns the RLP for this account.
pub fn trie_account_rlp(acc: &PlainAccount) -> Bytes {
let mut stream = RlpStream::new_list(4);
stream.append(&acc.info.nonce);
stream.append(&acc.info.balance);
stream.append(&{
sec_trie_root::<KeccakHasher, _, _, _>(
acc.storage
.iter()
.filter(|(_k, &v)| v != U256::ZERO)
.map(|(&k, v)| (H256::from(k.to_be_bytes()), rlp::encode(v))),
)
});
stream.append(&acc.info.code_hash.0.as_ref());
stream.out().freeze()
impl TrieAccount {
#[inline(always)]
fn new(acc: &PlainAccount) -> Self {
Self {
nonce: acc.info.nonce,
balance: acc.info.balance,
root_hash: sec_trie_root::<KeccakHasher, _, _, _>(
acc.storage
.iter()
.filter(|(_k, &v)| v != U256::ZERO)
.map(|(k, v)| (k.to_be_bytes::<32>(), alloy_rlp::encode_fixed_size(v))),
),
code_hash: acc.info.code_hash,
}
}
}

pub fn trie_root(acc_data: Vec<(H160, Bytes)>) -> B256 {
B256(sec_trie_root::<KeccakHasher, _, _, _>(acc_data).0)
#[inline]
pub fn trie_root<I, A, B>(input: I) -> B256
where
I: IntoIterator<Item = (A, B)>,
A: AsRef<[u8]>,
B: AsRef<[u8]>,
{
sec_trie_root::<KeccakHasher, _, _, _>(input)
}

#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct KeccakHasher;

impl Hasher for KeccakHasher {
type Out = H256;
type Out = B256;
type StdHasher = PlainHasher;
const LENGTH: usize = 32;

#[inline]
fn hash(x: &[u8]) -> Self::Out {
let out = Keccak256::digest(x);
H256::from_slice(out.as_slice())
keccak256(x)
}
}
77 changes: 11 additions & 66 deletions bins/revme/src/statetest/models/deserializer.rs
Original file line number Diff line number Diff line change
@@ -1,83 +1,28 @@
use std::str::FromStr;

use bytes::Bytes;
use revm::primitives::{B160, U256};
use serde::{
de::{self, Error},
Deserialize,
};
use revm::primitives::Address;
use serde::{de, Deserialize};

pub fn deserialize_str_as_u64<'de, D>(deserializer: D) -> Result<u64, D::Error>
where
D: de::Deserializer<'de>,
{
let string = String::deserialize(deserializer)?;

let output = if let Some(stripped) = string.strip_prefix("0x") {
u64::from_str_radix(stripped, 16).unwrap()
if let Some(stripped) = string.strip_prefix("0x") {
u64::from_str_radix(stripped, 16)
} else {
string.parse().unwrap()
};

Ok(output)
}

pub fn deserialize_str_as_u256<'de, D>(deserializer: D) -> Result<U256, D::Error>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

where
D: de::Deserializer<'de>,
{
let string = String::deserialize(deserializer)?;
let output = string.parse().unwrap();

Ok(output)
}

pub fn deserialize_vec_as_vec_bytes<'de, D>(deserializer: D) -> Result<Vec<Bytes>, D::Error>
where
D: de::Deserializer<'de>,
{
let strings: Vec<String> = Vec::<String>::deserialize(deserializer)?;

let mut out = Vec::new();
for string in strings {
out.push(
hex::decode(string.strip_prefix("0x").unwrap_or(&string))
.map_err(D::Error::custom)?
.into(),
)
string.parse()
}
Ok(out)
.map_err(serde::de::Error::custom)
}

pub fn deserialize_maybe_empty<'de, D>(deserializer: D) -> Result<Option<B160>, D::Error>
pub fn deserialize_maybe_empty<'de, D>(deserializer: D) -> Result<Option<Address>, D::Error>
where
D: de::Deserializer<'de>,
{
let string: String = String::deserialize(deserializer)?;
let string = String::deserialize(deserializer)?;
if string.is_empty() {
return Ok(None);
Ok(None)
} else {
string.parse().map_err(de::Error::custom).map(Some)
}
Ok(Some(B160::from_str(&string).map_err(D::Error::custom)?))
}

pub fn deserialize_str_as_bytes<'de, D>(deserializer: D) -> Result<Bytes, D::Error>
where
D: de::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;

Ok(hex::decode(s.strip_prefix("0x").unwrap_or(&s))
.map_err(D::Error::custom)?
.into())
}

pub fn deserialize_opt_str_as_bytes<'de, D>(deserializer: D) -> Result<Option<Bytes>, D::Error>
where
D: de::Deserializer<'de>,
{
#[derive(Debug, Deserialize)]
struct WrappedValue(#[serde(deserialize_with = "deserialize_str_as_bytes")] Bytes);

Option::<WrappedValue>::deserialize(deserializer)
.map(|opt_wrapped: Option<WrappedValue>| opt_wrapped.map(|wrapped: WrappedValue| wrapped.0))
}
Loading