Skip to content

Commit

Permalink
Use RPC batch requests where possible
Browse files Browse the repository at this point in the history
  • Loading branch information
Brechtpd committed Apr 19, 2024
1 parent 11cc300 commit 2062efb
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 77 deletions.
22 changes: 13 additions & 9 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ lazy_static = "1.4.0"
once_cell = "1.8.0"
thiserror = "1.0"
reqwest = { version = "0.11.22", features = ["json"] }
reqwest_alloy = { package = "reqwest", version = "0.12.4", features = ["json"] }
sha2 = "0.10.8"
proptest = "1.4.0"
rlp = "0.5.2"
Expand Down
1 change: 1 addition & 0 deletions host/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ lazy_static = { workspace = true }
once_cell = { workspace = true }
thiserror = { workspace = true }
reqwest = { workspace = true }
reqwest_alloy = { workspace = true }
sha2 = { workspace = true }
proptest = { workspace = true }
c-kzg = { workspace = true }
Expand Down
14 changes: 6 additions & 8 deletions host/src/preflight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@ use alloy_consensus::{
pub use alloy_primitives::*;
use alloy_provider::{Provider, ProviderBuilder, ReqwestProvider, RootProvider};
pub use alloy_rlp as rlp;
use alloy_rpc_client::RpcClient;
use alloy_rpc_types::{
Block as AlloyBlock, BlockTransactions, Filter, Transaction as AlloyRpcTransaction,
};
use alloy_sol_types::{SolCall, SolEvent};
use alloy_transport_http::Http;
use anyhow::{anyhow, bail, Result};
use c_kzg::{Blob, KzgCommitment};
use hashbrown::HashSet;
Expand All @@ -30,7 +28,6 @@ use raiko_primitives::{
mpt::proofs_to_tries,
};
use serde::{Deserialize, Serialize};
use url::Url;

use crate::provider_db::{MeasuredProviderDb, ProviderDb};

Expand All @@ -42,8 +39,9 @@ pub fn preflight(
l1_rpc_url: Option<String>,
beacon_rpc_url: Option<String>,
) -> Result<GuestInput> {
let http = Http::new(Url::parse(&rpc_url.clone().unwrap()).expect("invalid rpc url"));
let provider = ProviderBuilder::new().provider(RootProvider::new(RpcClient::new(http, true)));
let provider = ProviderBuilder::new().provider(RootProvider::new_http(
reqwest::Url::parse(&rpc_url.clone().unwrap()).expect("invalid rpc url"),
));

let measurement = Measurement::start("Fetching block data...", true);

Expand All @@ -56,9 +54,9 @@ pub fn preflight(
println!("block transactions: {:?}", block.transactions.len());

let taiko_guest_input = if network.is_taiko() {
let http_l1 = Http::new(Url::parse(&l1_rpc_url.clone().unwrap()).expect("invalid rpc url"));
let provider_l1 =
ProviderBuilder::new().provider(RootProvider::new(RpcClient::new(http_l1, true)));
let provider_l1 = ProviderBuilder::new().provider(RootProvider::new_http(
reqwest::Url::parse(&l1_rpc_url.clone().unwrap()).expect("invalid rpc url"),
));

// Decode the anchor tx to find out which L1 blocks we need to fetch
let anchor_tx = match &block.transactions {
Expand Down
136 changes: 76 additions & 60 deletions host/src/provider_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@ use std::{
};

use alloy_consensus::Header as AlloyConsensusHeader;
use alloy_primitives::{Bytes, Uint};
use alloy_provider::{Provider, ReqwestProvider};
use alloy_rpc_client::{ClientBuilder, RpcClient};
use alloy_rpc_types::{Block, BlockId, EIP1186AccountProofResponse};
use alloy_transport_http::Http;
use raiko_lib::{clear_line, inplace_print, mem_db::MemDb, print_duration, taiko_utils::to_header};
use raiko_primitives::{mpt::KECCAK_EMPTY, Address, B256, U256};
use raiko_primitives::{Address, B256, U256};
use reqwest_alloy::Client;
use revm::{
primitives::{Account, AccountInfo, Bytecode, HashMap},
Database, DatabaseCommit,
Expand All @@ -31,6 +35,7 @@ use crate::preflight::get_block;

pub struct ProviderDb {
pub provider: ReqwestProvider,
pub client: RpcClient<Http<Client>>,
pub block_number: u64,
pub initial_db: MemDb,
pub initial_headers: HashMap<u64, AlloyConsensusHeader>,
Expand All @@ -54,8 +59,12 @@ impl ProviderDb {
initial_headers.insert(block_number, to_header(&block.header));
}
}
// The client used for batch requests
let client = ClientBuilder::default()
.reqwest_http(reqwest::Url::parse(&provider.client().transport().url()).unwrap());
ProviderDb {
provider,
client,
block_number,
initial_db,
initial_headers,
Expand All @@ -81,19 +90,37 @@ impl ProviderDb {
) -> Result<HashMap<Address, EIP1186AccountProofResponse>, anyhow::Error> {
let mut storage_proofs = HashMap::new();
let mut idx = offset;
for (address, keys) in storage_keys {

// Create a batch for all storage proofs
let mut batch = self.client.new_batch();

// Collect all requests
let mut requests = Vec::new();
for (address, keys) in storage_keys.clone() {
requests.push((
Box::pin(
batch
.add_call::<_, EIP1186AccountProofResponse>(
"eth_getProof",
&(address, keys.clone(), BlockId::from(block_number)),
)
.unwrap(),
),
keys.len(),
));
}

// Send the batch
self.async_executor.block_on(async { batch.send().await })?;

// Collect the data from the batch
for (request, num_keys) in requests.into_iter() {
inplace_print(&format!(
"fetching storage proof {idx}/{num_storage_proofs}..."
));

let indices = keys.iter().map(|x| x.to_be_bytes().into()).collect();
let proof = self.async_executor.block_on(async {
self.provider
.get_proof(address, indices, Some(BlockId::from(block_number)))
.await
})?;
storage_proofs.insert(address, proof);
idx += keys.len();
let proof = self.async_executor.block_on(async { request.await })?;
storage_proofs.insert(proof.address, proof);
idx += num_keys;
}
clear_line();

Expand Down Expand Up @@ -186,57 +213,46 @@ impl Database for ProviderDb {
return Ok(db_result);
}

let use_get_proof = true;
let account_info = if use_get_proof {
let proof = self.async_executor.block_on(async {
self.provider
.get_proof(address, Vec::new(), Some(BlockId::from(self.block_number)))
.await
})?;

// Only fetch the code if we know it's not empty
let code = if proof.code_hash.0 != KECCAK_EMPTY.0 {
let code = self.async_executor.block_on(async {
self.provider
.get_code_at(address, BlockId::from(self.block_number))
.await
})?;
Bytecode::new_raw(code)
} else {
Bytecode::new()
};

AccountInfo::new(
proof.balance,
proof.nonce.try_into().unwrap(),
proof.code_hash,
code,
// Create a batch request for all account values
let mut batch = self.client.new_batch();

let nonce_request = batch
.add_call::<_, Uint<64, 1>>(
"eth_getTransactionCount",
&(address, Some(BlockId::from(self.block_number))),
)
.unwrap();
let balance_request = batch
.add_call::<_, Uint<256, 4>>(
"eth_getBalance",
&(address, Some(BlockId::from(self.block_number))),
)
} else {
// Get the nonce, balance, and code to reconstruct the account.
let nonce = self.async_executor.block_on(async {
self.provider
.get_transaction_count(address, Some(BlockId::from(self.block_number)))
.await
})?;
let balance = self.async_executor.block_on(async {
self.provider
.get_balance(address, Some(BlockId::from(self.block_number)))
.await
})?;
let code = self.async_executor.block_on(async {
self.provider
.get_code_at(address, BlockId::from(self.block_number))
.await
})?;

AccountInfo::new(
balance,
nonce.try_into().unwrap(),
Bytecode::new_raw(code.clone()).hash_slow(),
Bytecode::new_raw(code),
.unwrap();
let code_request = batch
.add_call::<_, Bytes>(
"eth_getCode",
&(address, Some(BlockId::from(self.block_number))),
)
};
.unwrap();

// Send the batch
self.async_executor.block_on(async { batch.send().await })?;

// Collect the data from the batch
let (nonce, balance, code) = self.async_executor.block_on(async {
Ok::<_, Self::Error>((
nonce_request.await?,
balance_request.await?,
code_request.await?,
))
})?;

let account_info = AccountInfo::new(
balance,
nonce.try_into().unwrap(),
Bytecode::new_raw(code.clone()).hash_slow(),
Bytecode::new_raw(code),
);

// Insert the account into the initial database.
self.initial_db
Expand Down

0 comments on commit 2062efb

Please sign in to comment.