add simulated call support

This commit is contained in:
Noah Citron 2022-08-23 21:33:48 -04:00
parent 6277843243
commit 748af6ce95
8 changed files with 311 additions and 16 deletions

189
Cargo.lock generated
View File

@ -14,6 +14,17 @@ dependencies = [
"opaque-debug 0.3.0",
]
[[package]]
name = "ahash"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [
"getrandom",
"once_cell",
"version_check",
]
[[package]]
name = "aho-corasick"
version = "0.7.18"
@ -29,6 +40,12 @@ version = "1.0.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1485d4d2cc45e7b201ee3767015c96faa5904387c9d87c6efdd0fb511f12d305"
[[package]]
name = "arrayref"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
[[package]]
name = "arrayvec"
version = "0.7.2"
@ -885,9 +902,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
[[package]]
name = "futures"
version = "0.3.21"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e"
checksum = "ab30e97ab6aacfe635fad58f22c2bb06c8b685f7421eb1e064a729e2a5f481fa"
dependencies = [
"futures-channel",
"futures-core",
@ -900,9 +917,9 @@ dependencies = [
[[package]]
name = "futures-channel"
version = "0.3.21"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
checksum = "2bfc52cbddcfd745bf1740338492bb0bd83d76c67b445f91c5fb29fae29ecaa1"
dependencies = [
"futures-core",
"futures-sink",
@ -910,15 +927,15 @@ dependencies = [
[[package]]
name = "futures-core"
version = "0.3.21"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
checksum = "d2acedae88d38235936c3922476b10fced7b2b68136f5e3c03c2d5be348a1115"
[[package]]
name = "futures-executor"
version = "0.3.21"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6"
checksum = "1d11aa21b5b587a64682c0094c2bdd4df0076c5324961a40cc3abd7f37930528"
dependencies = [
"futures-core",
"futures-task",
@ -944,9 +961,9 @@ dependencies = [
[[package]]
name = "futures-macro"
version = "0.3.21"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
checksum = "0db9cce532b0eae2ccf2766ab246f114b56b9cf6d445e00c2549fbc100ca045d"
dependencies = [
"proc-macro2",
"quote",
@ -955,15 +972,15 @@ dependencies = [
[[package]]
name = "futures-sink"
version = "0.3.21"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
checksum = "ca0bae1fe9752cf7fd9b0064c674ae63f97b37bc714d745cbde0afb7ec4e6765"
[[package]]
name = "futures-task"
version = "0.3.21"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
checksum = "842fc63b931f4056a24d59de13fb1272134ce261816e063e634ad0c15cdc5306"
[[package]]
name = "futures-timer"
@ -977,9 +994,9 @@ dependencies = [
[[package]]
name = "futures-util"
version = "0.3.21"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
checksum = "f0828a5471e340229c11c77ca80017937ce3c58cb788a17e5f1c2d5c485a9577"
dependencies = [
"futures-channel",
"futures-core",
@ -1131,6 +1148,9 @@ name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [
"ahash",
]
[[package]]
name = "hashers"
@ -1563,6 +1583,9 @@ name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
dependencies = [
"spin",
]
[[package]]
name = "libc"
@ -1575,11 +1598,14 @@ name = "lightclient"
version = "0.1.0"
dependencies = [
"blst",
"bytes",
"ethers",
"eyre",
"futures",
"hex",
"jsonrpsee",
"reqwest",
"revm",
"serde",
"ssz-rs",
"tokio",
@ -1652,6 +1678,20 @@ dependencies = [
"tempfile",
]
[[package]]
name = "num"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606"
dependencies = [
"num-bigint",
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-bigint"
version = "0.4.3"
@ -1663,6 +1703,15 @@ dependencies = [
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19"
dependencies = [
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.45"
@ -1673,6 +1722,29 @@ dependencies = [
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
dependencies = [
"autocfg",
"num-bigint",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.15"
@ -1692,6 +1764,27 @@ dependencies = [
"libc",
]
[[package]]
name = "num_enum"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9"
dependencies = [
"num_enum_derive",
]
[[package]]
name = "num_enum_derive"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "once_cell"
version = "1.13.0"
@ -2127,6 +2220,39 @@ dependencies = [
"winreg",
]
[[package]]
name = "revm"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab402ae244afdd560b2aa710df5af557bc791b1cca6fec174ced0cf781e13134"
dependencies = [
"arrayref",
"auto_impl",
"bytes",
"hashbrown",
"num_enum",
"primitive-types",
"revm_precompiles",
"rlp",
"sha3",
]
[[package]]
name = "revm_precompiles"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af88e7e9feb30cc4ed64645f09b966e84a1f6be56551ce5f1691105def45705d"
dependencies = [
"bytes",
"num",
"primitive-types",
"ripemd",
"secp256k1",
"sha2 0.10.2",
"sha3",
"substrate-bn",
]
[[package]]
name = "rfc6979"
version = "0.3.0"
@ -2322,6 +2448,24 @@ dependencies = [
"zeroize",
]
[[package]]
name = "secp256k1"
version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ece73253dd9e1fb540ff324eae554113a31c25fb598d22fd13b088a6a03f90d"
dependencies = [
"secp256k1-sys",
]
[[package]]
name = "secp256k1-sys"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7058dc8eaf3f2810d7828680320acda0b25a288f6d288e19278e249bbf74226b"
dependencies = [
"cc",
]
[[package]]
name = "security-framework"
version = "2.6.1"
@ -2603,6 +2747,19 @@ dependencies = [
"syn",
]
[[package]]
name = "substrate-bn"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c"
dependencies = [
"byteorder",
"crunchy",
"lazy_static",
"rand",
"rustc-hex",
]
[[package]]
name = "subtle"
version = "2.4.1"

View File

@ -15,3 +15,6 @@ ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs" }
blst = "0.3.10"
ethers = "0.17.0"
jsonrpsee = { version = "0.15.1", features = ["full"] }
revm = "1.9.0"
bytes = "1.2.1"
futures = "0.3.23"

View File

@ -4,6 +4,7 @@ use eyre::Result;
use crate::consensus::types::Header;
use crate::consensus::ConsensusClient;
use crate::execution::ExecutionClient;
use crate::execution::evm::Evm;
pub struct Client {
consensus: ConsensusClient,
@ -29,6 +30,12 @@ impl Client {
self.consensus.sync().await
}
pub async fn call(&mut self, to: &Address, calldata: &Vec<u8>, value: U256) -> Result<Vec<u8>> {
let payload = self.consensus.get_execution_payload().await?;
let mut evm = Evm::new(self.execution.clone(), payload);
evm.call(to, calldata, value)
}
pub async fn get_balance(&mut self, address: &Address) -> Result<U256> {
let payload = self.consensus.get_execution_payload().await?;
let account = self.execution.get_account(&address, None, &payload).await?;

118
src/execution/evm.rs Normal file
View File

@ -0,0 +1,118 @@
use std::str::FromStr;
use bytes::Bytes;
use eyre::Result;
use ethers::prelude::{U256, H256, H160, Address};
use revm::{Database, Bytecode, AccountInfo, EVM, Env, TransactTo, TransactOut};
use futures::executor::block_on;
use crate::consensus::types::ExecutionPayload;
use super::ExecutionClient;
pub struct Evm {
evm: EVM<ProofDB>
}
impl Evm {
pub fn new(execution: ExecutionClient, payload: ExecutionPayload) -> Self {
let mut evm: EVM<ProofDB> = EVM::new();
let db = ProofDB::new(execution, payload);
evm.database(db);
Evm { evm }
}
pub fn call(&mut self, to: &Address, calldata: &Vec<u8>, value: U256) -> Result<Vec<u8>> {
let mut env = Env::default();
let mut tx = revm::TxEnv::default();
tx.transact_to = TransactTo::Call(*to);
tx.data = Bytes::from(calldata.clone());
tx.value = value;
env.tx = tx;
self.evm.env = env;
let output = self.evm.transact().1;
if let Some(err) = &self.evm.db.as_ref().unwrap().error {
return Err(eyre::eyre!(err.clone()));
}
match output {
TransactOut::None => Err(eyre::eyre!("Invalid Call")),
TransactOut::Create(..) => Err(eyre::eyre!("Invalid Call")),
TransactOut::Call(bytes) => Ok(bytes.to_vec()),
}
}
}
struct ProofDB {
execution: ExecutionClient,
payload: ExecutionPayload,
error: Option<String>,
}
impl ProofDB {
pub fn new(execution: ExecutionClient, payload: ExecutionPayload) -> Self {
ProofDB {
execution,
payload,
error: None,
}
}
}
impl Database for ProofDB {
fn basic(&mut self, address: H160) -> AccountInfo {
self.error = None;
if is_precompile(&address) {
return AccountInfo::default()
}
let account_future = self.execution.get_account(&address, None, &self.payload);
let account_res = block_on(account_future);
if account_res.is_err() {
self.error = Some(account_res.as_ref().err().unwrap().to_string())
}
let account = account_res.unwrap();
let bytecode_future = self.execution.get_code(&address, &self.payload);
let bytecode_res = block_on(bytecode_future);
if bytecode_res.is_err() {
self.error = Some(bytecode_res.as_ref().err().unwrap().to_string())
}
let bytecode = bytecode_res.unwrap();
let bytecode = Bytecode::new_raw(Bytes::from(bytecode));
AccountInfo::new(account.balance, account.nonce.as_u64(), bytecode)
}
fn block_hash(&mut self, _number: U256) -> H256 {
H256::default()
}
fn storage(&mut self, address: H160, slot: U256) -> U256 {
let slots = [slot];
let account_future = self.execution.get_account(&address, Some(&slots), &self.payload);
let account_res = block_on(account_future);
if account_res.is_err() {
self.error = Some(account_res.as_ref().err().unwrap().to_string());
}
let account = account_res.unwrap();
*account.slots.get(&slot).unwrap()
}
fn code_by_hash(&mut self, _code_hash: H256) -> Bytecode {
panic!("should never be called");
}
}
fn is_precompile(address: &Address) -> bool {
address.le(&Address::from_str("0x0000000000000000000000000000000000000009").unwrap())
}

View File

@ -12,6 +12,7 @@ use super::types::Account;
use crate::common::utils::hex_str_to_bytes;
use crate::consensus::types::ExecutionPayload;
#[derive(Clone)]
pub struct ExecutionClient {
rpc: Rpc,
}

View File

@ -1,4 +1,5 @@
pub mod types;
pub mod evm;
mod execution;
pub use execution::*;

View File

@ -11,6 +11,7 @@ use crate::common::utils::{address_to_hex_string, hex_str_to_bytes, u64_to_hex_s
use super::types::Proof;
#[derive(Clone)]
pub struct Rpc {
rpc: String,
}

View File

@ -5,6 +5,8 @@ use eyre::Result;
use client::Client;
use crate::common::utils::hex_str_to_bytes;
pub mod client;
pub mod common;
pub mod consensus;
@ -28,10 +30,15 @@ async fn main() -> Result<()> {
let code = client.get_code(&address).await?;
let storage_value = client.get_storage_at(&address, U256::from(0)).await?;
let owner_calldata = hex_str_to_bytes("0x8da5cb5b")?;
let value = U256::from(0);
let owner = client.call(&address, &owner_calldata, value).await?;
println!("balance: {}", balance);
println!("nonce: {}", nonce);
println!("code: 0x{}...", hex::encode(code[..5].to_vec()));
println!("value at slot 0: 0x{:x}", storage_value);
println!("result of calling owner() on address: {}", hex::encode(owner));
Ok(())
}