Skip to content

Commit

Permalink
add touched_state mod, refactored rpc functions
Browse files Browse the repository at this point in the history
  • Loading branch information
xqft committed Dec 2, 2024
1 parent 446e4c9 commit 8bf00dc
Show file tree
Hide file tree
Showing 6 changed files with 296 additions and 143 deletions.
5 changes: 5 additions & 0 deletions Cargo.lock

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

16 changes: 16 additions & 0 deletions crates/l2/prover/bench/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ edition = "2021"
[dependencies]
ethrex-core.workspace = true
ethrex-rlp.workspace = true
ethrex-vm.workspace = true

#rsp-host-executor = { git = "https://github.com/succinctlabs/rsp" }
#rsp-client-executor = { git = "https://github.com/succinctlabs/rsp" }
Expand All @@ -16,3 +17,18 @@ clap = { version = "4.5.21", features = ["derive"] }
serde.workspace = true
hex.workspace = true
serde_json.workspace = true

revm = { version = "14.0.3", features = [
"serde",
"std",
"serde-json",
"optional_no_base_fee",
"optional_block_gas_limit",
], default-features = false }

# These dependencies must be kept up to date with the corresponding revm version, otherwise errors may pop up because of trait implementation mismatches
revm-inspectors = { version = "0.8.1" }
revm-primitives = { version = "10.0.0", features = [
"std",
], default-features = false }
futures-util = "0.3.31"
139 changes: 1 addition & 138 deletions crates/l2/prover/bench/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,138 +1 @@
use ethrex_core::{
types::{AccountState, Block},
Address,
};
use ethrex_rlp::decode::RLPDecode;

use serde::Deserialize;
use serde_json::json;

pub async fn get_block(rpc_url: &str, block_number: usize) -> Result<Block, String> {
let client = reqwest::Client::new();

let block_number = format!("0x{block_number:x}");
let request = &json!({
"id": 1,
"jsonrpc": "2.0",
"method": "debug_getRawBlock",
"params": [block_number]
});

let response = client
.post(rpc_url)
.json(request)
.send()
.await
.map_err(|err| err.to_string())?;

response
.json::<serde_json::Value>()
.await
.map_err(|err| err.to_string())
.and_then(|json| {
json.get("result")
.cloned()
.ok_or("failed to get result from response".to_string())
})
.and_then(|result| serde_json::from_value::<String>(result).map_err(|err| err.to_string()))
.and_then(|hex_encoded_block| {
hex::decode(hex_encoded_block.trim_start_matches("0x")).map_err(|err| err.to_string())
})
.and_then(|encoded_block| {
Block::decode_unfinished(&encoded_block)
.map_err(|err| err.to_string())
.map(|decoded| decoded.0)
})
}

pub async fn get_account(
rpc_url: &str,
block_number: usize,
address: Address,
) -> Result<AccountState, String> {
let client = reqwest::Client::new();

let block_number = format!("0x{block_number:x}");
let address = format!("0x{address:x}");

let request = &json!(
{
"id": 1,
"jsonrpc": "2.0",
"method": "eth_getProof",
"params":[address, [], block_number]
}
);
let response = client
.post(rpc_url)
.json(request)
.send()
.await
.map_err(|err| err.to_string())?;

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct AccountProof {
balance: String,
code_hash: String,
nonce: String,
storage_hash: String,
}

let account_proof: AccountProof = response
.json::<serde_json::Value>()
.await
.map_err(|err| err.to_string())
.and_then(|json| {
json.get("result")
.cloned()
.ok_or("failed to get result from response".to_string())
})
.and_then(|result| serde_json::from_value(result).map_err(|err| err.to_string()))?;

Ok(AccountState {
nonce: u64::from_str_radix(account_proof.nonce.trim_start_matches("0x"), 16)
.map_err(|_| "failed to parse nonce".to_string())?,
balance: account_proof
.balance
.parse()
.map_err(|_| "failed to parse balance".to_string())?,
storage_root: account_proof
.storage_hash
.parse()
.map_err(|_| "failed to parse storage root".to_string())?,
code_hash: account_proof
.code_hash
.parse()
.map_err(|_| "failed to parse code hash".to_string())?,
})
}

#[cfg(test)]
mod test {
use ethrex_core::Address;

use crate::{get_account, get_block};

const BLOCK_NUMBER: usize = 21315830;
const RPC_URL: &str = "<to complete>";
const VITALIK_ADDR: &str = "d8dA6BF26964aF9D7eEd9e03E53415D37aA96045";

#[ignore = "Needs to manually set RPC_URL"]
#[tokio::test]
async fn get_block_works() {
get_block(RPC_URL, BLOCK_NUMBER).await.unwrap();
}

#[ignore = "Needs to manually set RPC_URL"]
#[tokio::test]
async fn get_account_works() {
get_account(
RPC_URL,
BLOCK_NUMBER,
Address::from_slice(&hex::decode(VITALIK_ADDR).unwrap()),
)
.await
.unwrap();
}
}
pub mod rpc;
36 changes: 31 additions & 5 deletions crates/l2/prover/bench/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
use bench::get_block;
use bench::rpc::{get_account, get_block};
use clap::Parser;
use ethrex_vm::{execution_db::touched_state::get_touched_state, SpecId};
use futures_util::future::join_all;

const MAINNET_CHAIN_ID: u64 = 0x1;
const MAINNET_SPEC_ID: SpecId = SpecId::CANCUN;

#[derive(Parser, Debug)]
struct Args {
Expand All @@ -11,11 +16,32 @@ struct Args {

#[tokio::main]
async fn main() {
let args = Args::parse();
let Args {
rpc_url,
block_number,
} = Args::parse();

let block = get_block(args.rpc_url, args.block_number)
// fetch block
let block = get_block(&rpc_url, &block_number)
.await
.expect("failed");
.expect("failed to fetch block");

// get all accounts and storage keys touched during execution of block
let touched_state = get_touched_state(&block, MAINNET_CHAIN_ID, MAINNET_SPEC_ID)
.expect("failed to get touched state");

// fetch all accounts and storage touched
let _accounts = join_all(
touched_state
.iter()
.map(|(address, _)| get_account(&rpc_url, &block_number, address)),
)
.await
.into_iter()
.collect::<Result<Vec<_>, String>>()
.expect("failed to fetch accounts");
// TODO: storage

println!("Succesfully fetched block {}", block.hash());
// 4. create prover program input and execute. Measure time.
// 5. invoke rsp and execute too. Save in cache
}
136 changes: 136 additions & 0 deletions crates/l2/prover/bench/src/rpc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
use ethrex_core::{
types::{AccountState, Block},
Address,
};
use ethrex_rlp::decode::RLPDecode;

use serde::Deserialize;
use serde_json::json;

pub async fn get_block(rpc_url: &str, block_number: &usize) -> Result<Block, String> {
let client = reqwest::Client::new();

let block_number = format!("0x{block_number:x}");
let request = &json!({
"id": 1,
"jsonrpc": "2.0",
"method": "debug_getRawBlock",
"params": [block_number]
});

let response = client
.post(rpc_url)
.json(request)
.send()
.await
.map_err(|err| err.to_string())?;

response
.json::<serde_json::Value>()
.await
.map_err(|err| err.to_string())
.and_then(|json| {
json.get("result")
.cloned()
.ok_or("failed to get result from response".to_string())
})
.and_then(|result| serde_json::from_value::<String>(result).map_err(|err| err.to_string()))
.and_then(|hex_encoded_block| {
hex::decode(hex_encoded_block.trim_start_matches("0x")).map_err(|err| err.to_string())
})
.and_then(|encoded_block| {
Block::decode_unfinished(&encoded_block)
.map_err(|err| err.to_string())
.map(|decoded| decoded.0)
})
}

pub async fn get_account(
rpc_url: &str,
block_number: &usize,
address: &Address,
) -> Result<AccountState, String> {
let client = reqwest::Client::new();

let block_number = format!("0x{block_number:x}");
let address = format!("0x{address:x}");

let request = &json!(
{
"id": 1,
"jsonrpc": "2.0",
"method": "eth_getProof",
"params":[address, [], block_number]
}
);
let response = client
.post(rpc_url)
.json(request)
.send()
.await
.map_err(|err| err.to_string())?;

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct AccountProof {
balance: String,
code_hash: String,
nonce: String,
storage_hash: String,
}

let account_proof: AccountProof = response
.json::<serde_json::Value>()
.await
.map_err(|err| err.to_string())
.and_then(|json| {
json.get("result")
.cloned()
.ok_or("failed to get result from response".to_string())
})
.and_then(|result| serde_json::from_value(result).map_err(|err| err.to_string()))?;

Ok(AccountState {
nonce: u64::from_str_radix(account_proof.nonce.trim_start_matches("0x"), 16)
.map_err(|_| "failed to parse nonce".to_string())?,
balance: account_proof
.balance
.parse()
.map_err(|_| "failed to parse balance".to_string())?,
storage_root: account_proof
.storage_hash
.parse()
.map_err(|_| "failed to parse storage root".to_string())?,
code_hash: account_proof
.code_hash
.parse()
.map_err(|_| "failed to parse code hash".to_string())?,
})
}

#[cfg(test)]
mod test {
use ethrex_core::Address;

use super::*;

const BLOCK_NUMBER: usize = 21315830;
const RPC_URL: &str = "https://gateway-api.cabinet-node.com/eaebc3a9aca25671f165e4032b3453eb";
const VITALIK_ADDR: &str = "d8dA6BF26964aF9D7eEd9e03E53415D37aA96045";

#[tokio::test]
async fn get_block_works() {
get_block(RPC_URL, BLOCK_NUMBER).await.unwrap();
}

#[tokio::test]
async fn get_account_works() {
get_account(
RPC_URL,
BLOCK_NUMBER,
Address::from_slice(&hex::decode(VITALIK_ADDR).unwrap()),
)
.await
.unwrap();
}
}
Loading

0 comments on commit 8bf00dc

Please sign in to comment.