tests: add execution tests (#14)

* add execution rpc trait

* add account tests

* add code and tx tests

* add receipt tests

* add get block tests
This commit is contained in:
Noah Citron 2022-09-08 17:46:48 -04:00 committed by GitHub
parent a63d56a952
commit 40a6211c13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 385 additions and 28 deletions

2
Cargo.lock generated
View File

@ -980,6 +980,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
name = "execution" name = "execution"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"async-trait",
"blst", "blst",
"bytes", "bytes",
"common", "common",
@ -992,6 +993,7 @@ dependencies = [
"reqwest", "reqwest",
"revm", "revm",
"serde", "serde",
"serde_json",
"ssz-rs", "ssz-rs",
"tokio", "tokio",
"toml", "toml",

View File

@ -10,12 +10,13 @@ use consensus::rpc::nimbus_rpc::NimbusRpc;
use consensus::types::{ExecutionPayload, Header}; use consensus::types::{ExecutionPayload, Header};
use consensus::ConsensusClient; use consensus::ConsensusClient;
use execution::evm::Evm; use execution::evm::Evm;
use execution::rpc::http_rpc::HttpRpc;
use execution::types::{CallOpts, ExecutionBlock}; use execution::types::{CallOpts, ExecutionBlock};
use execution::ExecutionClient; use execution::ExecutionClient;
pub struct Client { pub struct Client {
consensus: ConsensusClient<NimbusRpc>, consensus: ConsensusClient<NimbusRpc>,
execution: ExecutionClient, execution: ExecutionClient<HttpRpc>,
config: Arc<Config>, config: Arc<Config>,
payloads: HashMap<u64, ExecutionPayload>, payloads: HashMap<u64, ExecutionPayload>,
block_hashes: HashMap<Vec<u8>, u64>, block_hashes: HashMap<Vec<u8>, u64>,

View File

@ -10,6 +10,7 @@ reqwest = { version = "0.11", features = ["json"] }
tokio = { version = "1", features = ["full"] } tokio = { version = "1", features = ["full"] }
eyre = "0.6.8" eyre = "0.6.8"
serde = { version = "1.0.143", features = ["derive"] } serde = { version = "1.0.143", features = ["derive"] }
serde_json = "1.0.85"
hex = "0.4.3" hex = "0.4.3"
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs" } ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs" }
blst = "0.3.10" blst = "0.3.10"
@ -20,6 +21,7 @@ bytes = "1.2.1"
futures = "0.3.23" futures = "0.3.23"
toml = "0.5.9" toml = "0.5.9"
triehash-ethereum = { git = "https://github.com/openethereum/parity-ethereum" } triehash-ethereum = { git = "https://github.com/openethereum/parity-ethereum" }
async-trait = "0.1.57"
common = { path = "../common" } common = { path = "../common" }
consensus = { path = "../consensus" } consensus = { path = "../consensus" }

View File

@ -11,18 +11,18 @@ use tokio::runtime::Runtime;
use consensus::types::ExecutionPayload; use consensus::types::ExecutionPayload;
use crate::types::CallOpts; use crate::{rpc::Rpc, types::CallOpts};
use super::ExecutionClient; use super::ExecutionClient;
pub struct Evm { pub struct Evm<R: Rpc> {
evm: EVM<ProofDB>, evm: EVM<ProofDB<R>>,
chain_id: u64, chain_id: u64,
} }
impl Evm { impl<R: Rpc> Evm<R> {
pub fn new(execution: ExecutionClient, payload: ExecutionPayload, chain_id: u64) -> Self { pub fn new(execution: ExecutionClient<R>, payload: ExecutionPayload, chain_id: u64) -> Self {
let mut evm: EVM<ProofDB> = EVM::new(); let mut evm: EVM<ProofDB<R>> = EVM::new();
let db = ProofDB::new(execution, payload); let db = ProofDB::new(execution, payload);
evm.database(db); evm.database(db);
@ -78,14 +78,14 @@ impl Evm {
} }
} }
struct ProofDB { struct ProofDB<R: Rpc> {
execution: ExecutionClient, execution: ExecutionClient<R>,
payload: ExecutionPayload, payload: ExecutionPayload,
error: Option<String>, error: Option<String>,
} }
impl ProofDB { impl<R: Rpc> ProofDB<R> {
pub fn new(execution: ExecutionClient, payload: ExecutionPayload) -> Self { pub fn new(execution: ExecutionClient<R>, payload: ExecutionPayload) -> Self {
ProofDB { ProofDB {
execution, execution,
payload, payload,
@ -104,7 +104,7 @@ impl ProofDB {
} }
} }
impl Database for ProofDB { impl<R: Rpc> Database for ProofDB<R> {
fn basic(&mut self, address: H160) -> AccountInfo { fn basic(&mut self, address: H160) -> AccountInfo {
if is_precompile(&address) { if is_precompile(&address) {
return AccountInfo::default(); return AccountInfo::default();

View File

@ -17,11 +17,11 @@ use super::rpc::Rpc;
use super::types::{Account, ExecutionBlock}; use super::types::{Account, ExecutionBlock};
#[derive(Clone)] #[derive(Clone)]
pub struct ExecutionClient { pub struct ExecutionClient<R: Rpc> {
rpc: Rpc, rpc: R,
} }
impl ExecutionClient { impl<R: Rpc> ExecutionClient<R> {
pub fn new(rpc: &str) -> Result<Self> { pub fn new(rpc: &str) -> Result<Self> {
let rpc = Rpc::new(rpc)?; let rpc = Rpc::new(rpc)?;
Ok(ExecutionClient { rpc }) Ok(ExecutionClient { rpc })
@ -175,6 +175,7 @@ impl ExecutionClient {
let expected_receipt_root = ordered_trie_root(receipts_encoded); let expected_receipt_root = ordered_trie_root(receipts_encoded);
let expected_receipt_root = H256::from_slice(&expected_receipt_root.to_fixed_bytes()); let expected_receipt_root = H256::from_slice(&expected_receipt_root.to_fixed_bytes());
println!("{}", hex::encode(expected_receipt_root));
let payload_receipt_root = H256::from_slice(&payload.receipts_root); let payload_receipt_root = H256::from_slice(&payload.receipts_root);
if expected_receipt_root != payload_receipt_root || !receipts.contains(&receipt) { if expected_receipt_root != payload_receipt_root || !receipts.contains(&receipt) {

View File

@ -1,8 +1,8 @@
pub mod evm; pub mod evm;
pub mod rpc;
pub mod types; pub mod types;
mod execution; mod execution;
pub use crate::execution::*; pub use crate::execution::*;
mod proof; mod proof;
mod rpc;

View File

@ -1,20 +1,24 @@
use async_trait::async_trait;
use ethers::prelude::{Address, Http}; use ethers::prelude::{Address, Http};
use ethers::providers::{Middleware, Provider}; use ethers::providers::{Middleware, Provider};
use ethers::types::{BlockId, Bytes, EIP1186ProofResponse, Transaction, TransactionReceipt, H256}; use ethers::types::{BlockId, Bytes, EIP1186ProofResponse, Transaction, TransactionReceipt, H256};
use eyre::Result; use eyre::Result;
use super::Rpc;
#[derive(Clone)] #[derive(Clone)]
pub struct Rpc { pub struct HttpRpc {
provider: Provider<Http>, provider: Provider<Http>,
} }
impl Rpc { #[async_trait]
pub fn new(rpc: &str) -> Result<Self> { impl Rpc for HttpRpc {
fn new(rpc: &str) -> Result<Self> {
let provider = Provider::try_from(rpc)?; let provider = Provider::try_from(rpc)?;
Ok(Rpc { provider }) Ok(HttpRpc { provider })
} }
pub async fn get_proof( async fn get_proof(
&self, &self,
address: &Address, address: &Address,
slots: &[H256], slots: &[H256],
@ -28,26 +32,23 @@ impl Rpc {
Ok(proof_response) Ok(proof_response)
} }
pub async fn get_code(&self, address: &Address, block: u64) -> Result<Vec<u8>> { async fn get_code(&self, address: &Address, block: u64) -> Result<Vec<u8>> {
let block = Some(BlockId::from(block)); let block = Some(BlockId::from(block));
let code = self.provider.get_code(*address, block).await?; let code = self.provider.get_code(*address, block).await?;
Ok(code.to_vec()) Ok(code.to_vec())
} }
pub async fn send_raw_transaction(&self, bytes: &Vec<u8>) -> Result<H256> { async fn send_raw_transaction(&self, bytes: &Vec<u8>) -> Result<H256> {
let bytes = Bytes::from(bytes.as_slice().to_owned()); let bytes = Bytes::from(bytes.as_slice().to_owned());
Ok(self.provider.send_raw_transaction(bytes).await?.tx_hash()) Ok(self.provider.send_raw_transaction(bytes).await?.tx_hash())
} }
pub async fn get_transaction_receipt( async fn get_transaction_receipt(&self, tx_hash: &H256) -> Result<Option<TransactionReceipt>> {
&self,
tx_hash: &H256,
) -> Result<Option<TransactionReceipt>> {
let receipt = self.provider.get_transaction_receipt(*tx_hash).await?; let receipt = self.provider.get_transaction_receipt(*tx_hash).await?;
Ok(receipt) Ok(receipt)
} }
pub async fn get_transaction(&self, tx_hash: &H256) -> Result<Option<Transaction>> { async fn get_transaction(&self, tx_hash: &H256) -> Result<Option<Transaction>> {
Ok(self.provider.get_transaction(*tx_hash).await?) Ok(self.provider.get_transaction(*tx_hash).await?)
} }
} }

View File

@ -0,0 +1,50 @@
use std::{fs::read_to_string, path::PathBuf};
use async_trait::async_trait;
use common::utils::hex_str_to_bytes;
use ethers::types::{Address, EIP1186ProofResponse, Transaction, TransactionReceipt, H256};
use eyre::Result;
use super::Rpc;
#[derive(Clone)]
pub struct MockRpc {
path: PathBuf,
}
#[async_trait]
impl Rpc for MockRpc {
fn new(rpc: &str) -> Result<Self> {
let path = PathBuf::from(rpc);
Ok(MockRpc { path })
}
async fn get_proof(
&self,
_address: &Address,
_slots: &[H256],
_block: u64,
) -> Result<EIP1186ProofResponse> {
let proof = read_to_string(self.path.join("proof.json"))?;
Ok(serde_json::from_str(&proof)?)
}
async fn get_code(&self, _address: &Address, _block: u64) -> Result<Vec<u8>> {
let code = read_to_string(self.path.join("code.json"))?;
hex_str_to_bytes(&code[0..code.len() - 1])
}
async fn send_raw_transaction(&self, _bytes: &Vec<u8>) -> Result<H256> {
Err(eyre::eyre!("not implemented"))
}
async fn get_transaction_receipt(&self, _tx_hash: &H256) -> Result<Option<TransactionReceipt>> {
let receipt = read_to_string(self.path.join("receipt.json"))?;
Ok(serde_json::from_str(&receipt)?)
}
async fn get_transaction(&self, _tx_hash: &H256) -> Result<Option<Transaction>> {
let tx = read_to_string(self.path.join("transaction.json"))?;
Ok(serde_json::from_str(&tx)?)
}
}

25
execution/src/rpc/mod.rs Normal file
View File

@ -0,0 +1,25 @@
use async_trait::async_trait;
use ethers::types::{Address, EIP1186ProofResponse, Transaction, TransactionReceipt, H256};
use eyre::Result;
pub mod http_rpc;
pub mod mock_rpc;
#[async_trait]
pub trait Rpc: Send + Clone + 'static {
fn new(rpc: &str) -> Result<Self>
where
Self: Sized;
async fn get_proof(
&self,
address: &Address,
slots: &[H256],
block: u64,
) -> Result<EIP1186ProofResponse>;
async fn get_code(&self, address: &Address, block: u64) -> Result<Vec<u8>>;
async fn send_raw_transaction(&self, bytes: &Vec<u8>) -> Result<H256>;
async fn get_transaction_receipt(&self, tx_hash: &H256) -> Result<Option<TransactionReceipt>>;
async fn get_transaction(&self, tx_hash: &H256) -> Result<Option<Transaction>>;
}

1
execution/testdata/code.json vendored Normal file

File diff suppressed because one or more lines are too long

18
execution/testdata/proof.json vendored Normal file
View File

@ -0,0 +1,18 @@
{
"address": "0x14f9d4af749609c1438528c0cce1cc3f6d411c47",
"accountProof": [
"0xf90211a071e881b8a14ffdfd37073cbfbcb6bb2c9231d0559440027fd00f0e8a2235aa34a0e84ac559924013eabff34253b21d302c3c30ad0496cae6a1ae2d93171f0ee2d7a0a6ef9fb82ab93a5ba0153998b19aaf272a7050506d8c3405964296d5f10b8d6aa04c95a5d292a544afefc594a747620e39eb172f8ba9bd1082668e0843cffefeefa0815f25eddd6abf24135df25e695fbe45567a1a8ee9bb83df9482b9e1ac5527dba0b9234f356908b44cc9ed4171894f6f40f4122fda4e5f5c82e984deec601a87fda0fe947db5baa6c4ccc8655f3cd3631c220f8dc07aafa44d2147be5d2ab21af555a0c75c86ef435e5d58f8161ca09e838b53af78e0b81f17ab67c702dcf465c48f08a05d4eb9221936f698f2338f560ead42b115a6dd409b15108579f082773166b0b4a052ac45eb7d301b373044ead47d2d4ee6f2313979540bca0ae798c0ccb3e61421a0b7433a507e6ffeef9624872b21a73c3fd5fb3d8f781d28da44b2bedda5208d5aa0522aa006cfd459900bf06651a03b426e6fcfd5532e093a807641bc10bbae9691a06f8fe64c907d1d2b75e411858e701c263a0622ef9335ae1433ea9e3bdf9d8315a024e3319b5c09742a511fc2d342eeaa1f1eb41a2a1c78f7a1ac9dab1bbd65f0d2a03bf8e1b5ced29303bb0045bf8b4fc6ae52f07d3136620d296901f494d7eaeebda0071e94edd3d657ad6f01ac0ca870dd174d48b904d4767906658c1db62fd716b780",
"0xf90211a0373c65c436fc03fe9fe3bc74631719de2de9ee93143830404f74f6d55ee8083da0e56bb1ef97ce46a4dfd53142a5f51986ce2103d68c2f609650173a65a5d74d03a040b5dac451091440dfd30276ad1bef64aafd51eebdda7071c8bd1337a606de19a027f8fadfbf130af518f236e2e337746585cc4d321f745d4caa24f1dc00676b05a00e5c404b0a407dbdd598ab842048fb294c910ef39f390adbc32bce46b2e34a71a0e43291d8b64138dd133accade91bd6a1a10b5bee1b336817f03ff375a17d7b1ca064d673999038d81f854510ad959267827e3bcd2841bae4ed3ad4e80c227acaf0a0c023b60b354c91de5144503087c0e47a8053a4ae94b81bb0201f4840cdc89ff6a0975eaf9e2c261da99052309b82ff2bd7675b005da56efa0c0efc341e3b68ed0fa088d9a8a786c5ed346781f0d470b90b82f0c7cac8c070959859fe3aba8e906b5ca0e8697941f517a90668257af41b975c0f1cdedc9762c3585e27b2eaec7eb41c4ca0f72a74ba3efd9e397daaa4ec939865e250978947b69e7069e026916201945ee4a07242ec29142d129f6927395d6ce481405f85d1453344529d99f98e20272fbc1aa06f33fb0bd4c80da83e3e85010cfeed3b19a665157e19806086d34c3b11846e67a0a4464bf01a4296d323821535817b20db9986f1ebcbcedd84803a09c53f4f0588a0e1d393beb40edab4c0aa74c566807f295c33a4a58f91d27f705b289fe41a51c980",
"0xf90211a0d8a32a972ccc40d028cfe098181fd498491d3205dedf45212119a40263608d79a0eba342773c0e6d2968acfcd885c54d5ab37bd5f85188fe46c764ed0e18f58350a0b94b1708163349d0281a4815d8320241fca4184f270f2ac5fcecd0f6eae9e3b1a043ddbf76e40f7cf55dcc248ee64bb3097e27553737ac53984d783f055b9caf3ea0843d7e62a73d0027d096fbb66e0f469043d4115ee22b1f28b5f1137a26ca8cdba0f015b37db0287d99cf919af2143e2d11302de8a679e21c1c5c66f5087158aa3da04d3464647b9bd42b67d4285446559e2bf719883a80526b18f79330898906b5fba0f6f7ab5218a48cc0e204b3fb68dbddf7ac79b168f0325ca915bb3ed1a3130be2a08910831666244e6983919fee3c477826f08255edee9351a9f865df1fc1c8d40ca04903a704c077aac79e59b5c44c3b79e3f6716015309a29b069b55453d3d15773a0b2ea8736d58291c8c31dbc20185702717f8c533b656fa1f570b4c52030c05479a0d04ddbbd951b8e5f37c5819e242d6d341bf3239519b8d4e1f874fa2de3082a4aa0397a19edf6b5f64a9b04d1428fd5ac953178c23510e3dcf50bb9614e556c5cbfa0bfb66a915ec5bc5344c3c7282ee62e94234664090763a1dab43a3f20e6199b31a01c2f46a9fc0f12c1a5f1f7ce20cac8d2827ee82b6e2acbea4c9628f81b1d130da05222b1d0263ac9bad858462ef349e6347b04167d5f2a62400332fcc18a595f2d80",
"0xf90211a0060b9dbbd560313dfa11d86e56f8117d76130d197f08a796770fcaca646b7e1fa0cbb0b6eb9383b11c038ff8a9d30df57042e819c6e4e83666486a9fc094ee3ec5a049de57ac42fa5258213ccff70ef43d6bba4948e0dbfc5851a42ca84c1255cc23a0957940bcb472f09053fbda2f73c59868dfd4a865dad792a1bc5dd7957f8f5376a05b1bde3ba31401a9a93e10156d06117aaacc4f9f56a0441f10ba8848f8f954a8a0cfa085c19fcc9e290c999abc7209e469d76a4115219d87e8f361d15829fe2d53a0849e508de302c48ce95e7ae5ff20969bccdd36e69c9e11f25fd9a2dd16b36319a03a56898360443bb212bd44bb6ffda43dc36912f6c7cfd9a4bb39e58c936270f9a068842c2394fcc47c2e87802e88aa1465d37f6e97828e1df33d1178e6b14692c3a0b052b4c48baff415ca25c11b9825696404226ec65bbfa0bbc214d61984e5aceea02bfdb2153896c75a21927912d7e422d811f30cdf0edbcb6cdf955398781d6b45a06e932ff247483a4dc084d3860a29ee16040b8002b564405bb9db6045f988d61da074734042a667e98e49ea665b5a90109a8fca222f0c0813d0ff6bae785497cd60a04ad321ecd7939bb4b754ee3b76fe1b06efd3a6d583fccf2c3049cfcfb7d27473a0890dbb8238beb7875f636725343cc47214582fb5e0c0937920815a37339a6960a0469b936445ed7be59190a11c49e1198d7b584d5e59d62d793265fbe8ce0a937480",
"0xf90211a01a991ab74e62008f16acbf7fbe7119469aea98f0b05308d279da5aa897fb9ce5a0dcd7d6ac32c17dda96d77f14115771757d9b3245bda0a1d457d3352b616437f9a0610fa0acd1afcc1b3209d9e561a619d729cfda4bfa639bf4108f63fd6666340aa0539fc55db43500d6b2abd40a064fc800fe814522921d2528df7afd8e80670b08a08065e71d206bf24e631661ecc0fb1351fc65b851f66a1fcf25b882fbccd69d8ba0e3c85725c51e251bf16bd8ddf396613454175833ecc083a20794a71a1b0ce91fa06768a52005a756d65276e791abbc6e64f0974044a4a1bfc0effd8e660778447ca05d1061535cdb4e2775810401d5f9d5f78765e1669ba2a3c003aae461466bb253a01e6f9ab043ac334d887f6c92b358acdc64709cbd725dedf53159b71ae1bdebfda0c799a3e48366551e882f3a0d494a3d9438def0a618089c2922da38f6fd9031c0a0019fa068a9bd23bdab5982bc0da260e11abdf4164445f67945ffd2512a74e27ba0df54f3672852d15d637ecf05a465c7213bfaea546dcad7a3653ba474067fe248a08f28bdc021a4753466a2c0e77cd5ac412c6863155f03a97ae9e2de7dd27edf8da035ae5bb7ee628fcc2bf3bbe12bbe4b5f5b1e5a6a4fdd5f7752dcd6b27d57ec77a07dc8f59a0a12dfbf045ff82165af0101b32e5cbf3d7ab2903a21919b9978efb7a069232faca7617690aa62a02344d2a2d54b8529d963d9f7c95a02ea3519cd41da80",
"0xf8f18080a00c668cef94cedbc21f3f2ff5795442f424c67c3bcbd300328660d8f2e6543b908080a05c86dc654307d6f084bc46ee572324e89bb3965211cf0216f03a5511f179d2daa0d6cabba9da3391114dbe866d21cd6bfde3496bb8f69786b1b1fafa224795226ba0d6d362d0161e94d6787b2165d61bf0ccc1b51c351b6178b647d1df2e1be69274a01338e1219a75007137581b7299d61cd66d74d3e7eed44e73cf166033c0030ed380a06b8cb01c204ddf7ae87ae9531ab3713d7679a630496e79c127c5d4662823d724a04d29b6aac81dfac338997a2a66a9338531732efb7f32ffb2a81df61a2291f8f78080808080",
"0xf851808080808080808080808080a032914585f84a102eefeca772a4f807beb731bfbc6b2c407c7685d0e1a294e6dba07784d7e02bf6c6a29570c630c76231a4ee251ba305f57148c1e140c1dcfe88d5808080",
"0xf86c9d3801d9ae5e62cc3f6bcde556599e2fe63f1fadf1dc7318cf0ae6482f84b84cf84a0186048c27395000a0f98486b87474ffe02e56b9e4b45558b99928e4c67bcd517918849e77bd68d113a0c6ca0679d7242fa080596f2fe2e6b172d9b927a6b52278343826e33745854327"
],
"balance": "0x48c27395000",
"codeHash": "0xc6ca0679d7242fa080596f2fe2e6b172d9b927a6b52278343826e33745854327",
"nonce": "0x1",
"storageHash": "0xf98486b87474ffe02e56b9e4b45558b99928e4c67bcd517918849e77bd68d113",
"storageProof": []
}

32
execution/testdata/receipt.json vendored Normal file
View File

@ -0,0 +1,32 @@
{
"transactionHash": "0x2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f",
"blockHash": "0x6663f197e991f5a0bb235f33ec554b9bd48c37b4f5002d7ac2abdfa99f86ac14",
"blockNumber": "0x72e9b5",
"logs": [
{
"transactionHash": "0x2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f",
"address": "0x326c977e6efc84e512bb9c30f76e30c160ed06fb",
"blockHash": "0x6663f197e991f5a0bb235f33ec554b9bd48c37b4f5002d7ac2abdfa99f86ac14",
"blockNumber": "0x72e9b5",
"data": "0x000000000000000000000000000000000000000000000001158e460913d00000",
"logIndex": "0x0",
"removed": false,
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x0000000000000000000000004281ecf07378ee595c564a59048801330f3084ee",
"0x0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0"
],
"transactionIndex": "0x0"
}
],
"contractAddress": null,
"effectiveGasPrice": "0x9502f908",
"cumulativeGasUsed": "0xca6a",
"from": "0x4281ecf07378ee595c564a59048801330f3084ee",
"gasUsed": "0xca6a",
"logsBloom": "0x00000000000000040000000000000000000000000000100008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000004000000000020000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000800000000400000001000000000000000000000000000000000000000000000",
"status": "0x1",
"to": "0x326c977e6efc84e512bb9c30f76e30c160ed06fb",
"transactionIndex": "0x0",
"type": "0x2"
}

21
execution/testdata/transaction.json vendored Normal file
View File

@ -0,0 +1,21 @@
{
"blockHash": "0x6663f197e991f5a0bb235f33ec554b9bd48c37b4f5002d7ac2abdfa99f86ac14",
"blockNumber": "0x72e9b5",
"hash": "0x2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f",
"accessList": [],
"chainId": "0x5",
"from": "0x4281ecf07378ee595c564a59048801330f3084ee",
"gas": "0xea60",
"gasPrice": "0x9502f908",
"input": "0xa9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000",
"maxFeePerGas": "0x9502f910",
"maxPriorityFeePerGas": "0x9502f900",
"nonce": "0x623355",
"r": "0xe1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868c",
"s": "0x786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167",
"to": "0x326c977e6efc84e512bb9c30f76e30c160ed06fb",
"transactionIndex": "0x0",
"type": "0x2",
"v": "0x0",
"value": "0x0"
}

View File

@ -0,0 +1,203 @@
use std::collections::HashMap;
use std::str::FromStr;
use ethers::types::{Address, H256, U256};
use ethers::utils::keccak256;
use ssz_rs::{List, Vector};
use common::utils::hex_str_to_bytes;
use consensus::types::ExecutionPayload;
use execution::rpc::mock_rpc::MockRpc;
use execution::ExecutionClient;
fn get_client() -> ExecutionClient<MockRpc> {
ExecutionClient::new("testdata/").unwrap()
}
#[tokio::test]
async fn test_get_account() {
let execution = get_client();
let address = Address::from_str("14f9D4aF749609c1438528C0Cce1cC3f6D411c47").unwrap();
let mut payload = ExecutionPayload::default();
payload.state_root = Vector::from_iter(
hex_str_to_bytes("0xaa02f5db2ee75e3da400d10f3c30e894b6016ce8a2501680380a907b6674ce0d")
.unwrap(),
);
let account = execution
.get_account(&address, None, &payload)
.await
.unwrap();
assert_eq!(
account.balance,
U256::from_str_radix("48c27395000", 16).unwrap()
);
}
#[tokio::test]
async fn test_get_account_bad_proof() {
let execution = get_client();
let address = Address::from_str("14f9D4aF749609c1438528C0Cce1cC3f6D411c47").unwrap();
let payload = ExecutionPayload::default();
let account_res = execution.get_account(&address, None, &payload).await;
assert!(account_res.is_err());
}
#[tokio::test]
async fn test_get_code() {
let execution = get_client();
let address = Address::from_str("14f9D4aF749609c1438528C0Cce1cC3f6D411c47").unwrap();
let mut payload = ExecutionPayload::default();
payload.state_root = Vector::from_iter(
hex_str_to_bytes("0xaa02f5db2ee75e3da400d10f3c30e894b6016ce8a2501680380a907b6674ce0d")
.unwrap(),
);
let code = execution.get_code(&address, &payload).await.unwrap();
let code_hash = keccak256(code);
assert_eq!(
code_hash.as_slice(),
&hex_str_to_bytes("0xc6ca0679d7242fa080596f2fe2e6b172d9b927a6b52278343826e33745854327")
.unwrap()
);
}
#[tokio::test]
async fn test_get_code_bad_proof() {
let execution = get_client();
let address = Address::from_str("14f9D4aF749609c1438528C0Cce1cC3f6D411c47").unwrap();
let payload = ExecutionPayload::default();
let code_res = execution.get_code(&address, &payload).await;
assert!(code_res.is_err());
}
#[tokio::test]
async fn test_get_tx() {
let execution = get_client();
let tx_hash =
H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap();
let mut payload = ExecutionPayload::default();
payload.transactions.push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap()));
let mut payloads = HashMap::new();
payloads.insert(7530933, payload);
let tx = execution
.get_transaction(&tx_hash, &payloads)
.await
.unwrap()
.unwrap();
assert_eq!(tx.hash(), tx_hash);
}
#[tokio::test]
async fn test_get_tx_bad_proof() {
let execution = get_client();
let tx_hash =
H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap();
let payload = ExecutionPayload::default();
let mut payloads = HashMap::new();
payloads.insert(7530933, payload);
let tx_res = execution.get_transaction(&tx_hash, &payloads).await;
assert!(tx_res.is_err());
}
#[tokio::test]
async fn test_get_tx_not_included() {
let execution = get_client();
let tx_hash =
H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap();
let payloads = HashMap::new();
let tx_opt = execution
.get_transaction(&tx_hash, &payloads)
.await
.unwrap();
assert!(tx_opt.is_none());
}
#[tokio::test]
async fn test_get_receipt() {
let execution = get_client();
let tx_hash =
H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap();
let mut payload = ExecutionPayload::default();
payload.receipts_root = Vector::from_iter(
hex_str_to_bytes("dd82a78eccb333854f0c99e5632906e092d8a49c27a21c25cae12b82ec2a113f")
.unwrap(),
);
payload.transactions.push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap()));
let mut payloads = HashMap::new();
payloads.insert(7530933, payload);
let receipt = execution
.get_transaction_receipt(&tx_hash, &payloads)
.await
.unwrap()
.unwrap();
assert_eq!(receipt.transaction_hash, tx_hash);
}
#[tokio::test]
async fn test_get_receipt_bad_proof() {
let execution = get_client();
let tx_hash =
H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap();
let mut payload = ExecutionPayload::default();
payload.transactions.push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap()));
let mut payloads = HashMap::new();
payloads.insert(7530933, payload);
let receipt_res = execution.get_transaction_receipt(&tx_hash, &payloads).await;
assert!(receipt_res.is_err());
}
#[tokio::test]
async fn test_get_receipt_not_included() {
let execution = get_client();
let tx_hash =
H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap();
let payloads = HashMap::new();
let receipt_opt = execution
.get_transaction_receipt(&tx_hash, &payloads)
.await
.unwrap();
assert!(receipt_opt.is_none());
}
#[test]
fn test_get_block() {
let execution = get_client();
let mut payload = ExecutionPayload::default();
payload.block_number = 12345;
let block = execution.get_block(&payload).unwrap();
assert_eq!(block.number, 12345);
}