Skip to content

Commit

Permalink
add get_block and make code optional
Browse files Browse the repository at this point in the history
  • Loading branch information
eshaan7 committed Feb 22, 2025
1 parent aea9141 commit 77dbd28
Show file tree
Hide file tree
Showing 13 changed files with 122 additions and 46 deletions.
2 changes: 1 addition & 1 deletion common/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub struct Account {
pub balance: U256,
pub nonce: u64,
pub code_hash: B256,
pub code: Vec<u8>,
pub code: Option<Vec<u8>>,
pub storage_hash: B256,
pub slots: HashMap<B256, U256>,
}
Expand Down
14 changes: 10 additions & 4 deletions core/src/client/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,20 @@ impl<N: NetworkSpec, C: Consensus<N::BlockResponse>> Node<N, C> {
pub async fn get_balance(&self, address: Address, tag: BlockTag) -> Result<U256> {
self.check_blocktag_age(&tag).await?;

let account = self.execution.get_account(address, None, tag).await?;
let account = self
.execution
.get_account(address, None, tag, false)
.await?;
Ok(account.balance)
}

pub async fn get_nonce(&self, address: Address, tag: BlockTag) -> Result<u64> {
self.check_blocktag_age(&tag).await?;

let account = self.execution.get_account(address, None, tag).await?;
let account = self
.execution
.get_account(address, None, tag, false)
.await?;
Ok(account.nonce)
}

Expand All @@ -107,8 +113,8 @@ impl<N: NetworkSpec, C: Consensus<N::BlockResponse>> Node<N, C> {
pub async fn get_code(&self, address: Address, tag: BlockTag) -> Result<Bytes> {
self.check_blocktag_age(&tag).await?;

let account = self.execution.get_account(address, None, tag).await?;
Ok(account.code.into())
let account = self.execution.get_account(address, None, tag, true).await?;
Ok(account.code.unwrap().into())
}

pub async fn get_storage_at(
Expand Down
2 changes: 2 additions & 0 deletions core/src/execution/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub trait ExecutionMethods<N: NetworkSpec, R: ExecutionRpc<N>>: Send + Sync {
address: Address,
slots: Option<&[B256]>,
tag: BlockTag,
include_code: bool,
) -> Result<Account>;
async fn get_transaction_receipt(&self, tx_hash: B256) -> Result<Option<N::ReceiptResponse>>;
async fn get_logs(&self, filter: &Filter) -> Result<Vec<Log>>;
Expand All @@ -40,6 +41,7 @@ pub trait ExecutionMethods<N: NetworkSpec, R: ExecutionRpc<N>>: Send + Sync {
block: Option<BlockId>,
) -> Result<HashMap<Address, Account>>;
async fn chain_id(&self) -> Result<u64>;
async fn get_block(&self, block_id: BlockId) -> Result<Option<N::BlockResponse>>;
async fn get_block_receipts(&self, block: BlockId) -> Result<Option<Vec<N::ReceiptResponse>>>;
async fn send_raw_transaction(&self, bytes: &[u8]) -> Result<B256>;
async fn new_filter(&self, filter: &Filter) -> Result<U256>;
Expand Down
36 changes: 26 additions & 10 deletions core/src/execution/client/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use alloy::rpc::types::{EIP1186AccountProofResponse, Filter, FilterChanges, Log}
use async_trait::async_trait;
use eyre::Result;
use futures::future::{join_all, try_join_all};
use revm::primitives::{AccessListItem, KECCAK_EMPTY};
use revm::primitives::AccessListItem;

use helios_common::{
network_spec::NetworkSpec,
Expand Down Expand Up @@ -47,6 +47,7 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>> ExecutionMethods<N, R> for ExecutionRpc
address: Address,
slots: Option<&[B256]>,
tag: BlockTag,
include_code: bool,
) -> Result<Account> {
let slots = slots.unwrap_or(&[]);
let block = self
Expand All @@ -60,7 +61,8 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>> ExecutionMethods<N, R> for ExecutionRpc
.get_proof(address, slots, block.header().number().into())
.await?;

self.verify_proof_to_account(&proof, &block).await
self.verify_proof_to_account(&proof, &block, include_code)
.await
}

async fn get_transaction_receipt(&self, tx_hash: B256) -> Result<Option<N::ReceiptResponse>> {
Expand Down Expand Up @@ -178,8 +180,12 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>> ExecutionMethods<N, R> for ExecutionRpc
let mut account_map = HashMap::new();
for chunk in list.chunks(PARALLEL_QUERY_BATCH_SIZE) {
let account_chunk_futs = chunk.iter().map(|account| {
let account_fut =
self.get_account(account.address, Some(account.storage_keys.as_slice()), tag);
let account_fut = self.get_account(
account.address,
Some(account.storage_keys.as_slice()),
tag,
true,
);
async move { (account.address, account_fut.await) }
});

Expand All @@ -198,6 +204,17 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>> ExecutionMethods<N, R> for ExecutionRpc
self.rpc.chain_id().await
}

async fn get_block(&self, block: BlockId) -> Result<Option<N::BlockResponse>> {
Ok(match block {
BlockId::Number(number_or_tag) => {
self.rpc
.get_block_by_number(number_or_tag, false.into())
.await?
}
BlockId::Hash(hash) => self.rpc.get_block(hash.into()).await.ok(),
})
}

async fn get_block_receipts(&self, block: BlockId) -> Result<Option<Vec<N::ReceiptResponse>>> {
self.rpc.get_block_receipts(block).await
}
Expand Down Expand Up @@ -228,21 +245,19 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>> ExecutionRpcClient<N, R> {
&self,
proof: &EIP1186AccountProofResponse,
block: &N::BlockResponse,
verify_code: bool,
) -> Result<Account> {
// Verify the account proof
verify_account_proof(proof, block.header().state_root())?;
// Verify the storage proofs, collecting the slot values
let slot_map = verify_storage_proof(proof)?;
// Verify the code hash
let code = if proof.code_hash == KECCAK_EMPTY || proof.code_hash == B256::ZERO {
Vec::new()
} else {
let code = if verify_code {
let code = self
.rpc
.get_code(proof.address, block.header().number().into())
.await?;
let code_hash = keccak256(&code);

if proof.code_hash != code_hash {
return Err(ExecutionError::CodeHashMismatch(
proof.address,
Expand All @@ -251,8 +266,9 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>> ExecutionRpcClient<N, R> {
)
.into());
}

code
Some(code)
} else {
None
};

Ok(Account {
Expand Down
34 changes: 20 additions & 14 deletions core/src/execution/client/verifiable_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use alloy::network::{BlockResponse, ReceiptResponse};
use alloy::primitives::{keccak256, Address, B256, U256};
use alloy::rlp;
use alloy::rpc::types::{EIP1186AccountProofResponse, Filter, FilterChanges, Log};
use alloy_trie::KECCAK_EMPTY;
use async_trait::async_trait;
use eyre::Result;

Expand Down Expand Up @@ -43,6 +42,7 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>, A: VerifiableApi<N>> ExecutionMethods<N
address: Address,
slots: Option<&[B256]>,
tag: BlockTag,
include_code: bool,
) -> Result<Account> {
let block = self
.state
Expand All @@ -58,7 +58,7 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>, A: VerifiableApi<N>> ExecutionMethods<N

let account_response = self
.api
.get_account(address, &slots, Some(block_id))
.get_account(address, &slots, Some(block_id), include_code)
.await?;

self.verify_account_response(address, account_response, &block)
Expand Down Expand Up @@ -148,6 +148,10 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>, A: VerifiableApi<N>> ExecutionMethods<N
Ok(chain_id)
}

async fn get_block(&self, block: BlockId) -> Result<Option<N::BlockResponse>> {
self.api.get_block(block).await
}

async fn get_block_receipts(&self, block: BlockId) -> Result<Option<Vec<N::ReceiptResponse>>> {
self.api.get_block_receipts(block).await
}
Expand Down Expand Up @@ -199,19 +203,21 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>, A: VerifiableApi<N>>
verify_account_proof(&proof, block.header().state_root())?;
// Verify the storage proofs, collecting the slot values
let slot_map = verify_storage_proof(&proof)?;
// Verify the code hash
let code = if proof.code_hash == KECCAK_EMPTY || proof.code_hash == B256::ZERO {
Vec::new()
} else {
let code_hash = keccak256(&account.code);

if proof.code_hash != code_hash {
return Err(
ExecutionError::CodeHashMismatch(address, code_hash, proof.code_hash).into(),
);
// Verify the code hash (if code is included in the response)
let code = match account.code {
Some(code) => {
let code_hash = keccak256(&code);
if proof.code_hash != code_hash {
return Err(ExecutionError::CodeHashMismatch(
address,
code_hash,
proof.code_hash,
)
.into());
}
Some(code.into())
}

account.code.into()
None => None,
};

Ok(Account {
Expand Down
8 changes: 4 additions & 4 deletions core/src/execution/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>, A: VerifiableApi<N>> EvmState<N, R, A>
StateAccess::Basic(address) => {
let account = self
.execution
.get_account(*address, None, self.block)
.get_account(*address, None, self.block, true)
.await?;

self.basic.insert(
Expand All @@ -168,15 +168,15 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>, A: VerifiableApi<N>> EvmState<N, R, A>
account.balance,
account.nonce,
account.code_hash,
Bytecode::new_raw(account.code.into()),
Bytecode::new_raw(account.code.unwrap().into()),
),
);
}
StateAccess::Storage(address, slot) => {
let slot_bytes = B256::from(*slot);
let account = self
.execution
.get_account(*address, Some(&[slot_bytes]), self.block)
.get_account(*address, Some(&[slot_bytes]), self.block, false)
.await?;

let storage = self.storage.entry(*address).or_default();
Expand Down Expand Up @@ -246,7 +246,7 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>, A: VerifiableApi<N>> EvmState<N, R, A>
account.balance,
account.nonce,
account.code_hash,
Bytecode::new_raw(account.code.into()),
Bytecode::new_raw(account.code.unwrap().into()),
),
);

Expand Down
7 changes: 5 additions & 2 deletions core/src/execution/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,11 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>, A: VerifiableApi<N>> ExecutionClient<N,
address: Address,
slots: Option<&[B256]>,
tag: BlockTag,
include_code: bool,
) -> Result<Account> {
self.client().get_account(address, slots, tag).await
self.client()
.get_account(address, slots, tag, include_code)
.await
}

pub async fn get_storage_at(
Expand All @@ -98,7 +101,7 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>, A: VerifiableApi<N>> ExecutionClient<N,
let storage_key = slot.into();

let account = self
.get_account(address, Some(&[storage_key]), block)
.get_account(address, Some(&[storage_key]), block, false)
.await?;

let value = account.slots.get(&storage_key);
Expand Down
13 changes: 12 additions & 1 deletion verifiable-api/client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub trait VerifiableApi<N: NetworkSpec>: Send + Clone + Sync + 'static {
address: Address,
storage_slots: &[U256],
block: Option<BlockId>,
include_code: bool,
) -> Result<AccountResponse>;
async fn get_transaction_receipt(
&self,
Expand All @@ -40,6 +41,7 @@ pub trait VerifiableApi<N: NetworkSpec>: Send + Clone + Sync + 'static {
) -> Result<AccessListResponse>;
// Methods just for compatibility (acts as a proxy)
async fn chain_id(&self) -> Result<ChainIdResponse>;
async fn get_block(&self, block_id: BlockId) -> Result<Option<N::BlockResponse>>;
async fn get_block_receipts(&self, block: BlockId) -> Result<Option<Vec<N::ReceiptResponse>>>;
async fn send_raw_transaction(&self, bytes: &[u8]) -> Result<SendRawTxResponse>;
async fn new_filter(&self, filter: &Filter) -> Result<NewFilterResponse>;
Expand Down Expand Up @@ -77,6 +79,7 @@ impl<N: NetworkSpec> VerifiableApi<N> for VerifiableApiClient {
address: Address,
storage_slots: &[U256],
block: Option<BlockId>,
include_code: bool,
) -> Result<AccountResponse> {
let url = format!("{}/eth/v1/proof/account/{}", self.base_url, address);
let mut request = self.client.get(&url);
Expand All @@ -86,6 +89,7 @@ impl<N: NetworkSpec> VerifiableApi<N> for VerifiableApiClient {
for slot in storage_slots {
request = request.query(&[("storageSlots", slot)]);
}
request = request.query(&[("includeCode", include_code)]);
let response = request.send().await?;
let response = response.json::<AccountResponse>().await?;
Ok(response)
Expand Down Expand Up @@ -188,8 +192,15 @@ impl<N: NetworkSpec> VerifiableApi<N> for VerifiableApiClient {
Ok(response)
}

async fn get_block(&self, block_id: BlockId) -> Result<Option<N::BlockResponse>> {
let url = format!("{}/eth/v1/block/{}", self.base_url, block_id);
let response = self.client.get(&url).send().await?;
let response = response.json::<Option<N::BlockResponse>>().await?;
Ok(response)
}

async fn get_block_receipts(&self, block: BlockId) -> Result<Option<Vec<N::ReceiptResponse>>> {
let url = format!("{}/eth/v1/block_receipts/{}", self.base_url, block);
let url = format!("{}/eth/v1/block/{}/receipts", self.base_url, block);
let response = self.client.get(&url).send().await?;
let response = response.json::<Option<Vec<N::ReceiptResponse>>>().await?;
Ok(response)
Expand Down
16 changes: 15 additions & 1 deletion verifiable-api/server/bin/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ fn map_server_err(e: Report) -> (StatusCode, Json<serde_json::Value>) {
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AccountProofQuery {
#[serde(default)]
include_code: bool,
#[serde(default)]
pub storage_slots: Vec<U256>,
pub block: Option<BlockId>,
Expand Down Expand Up @@ -105,13 +107,14 @@ impl TryInto<Filter> for LogsQuery {
pub async fn get_account<N: NetworkSpec, R: ExecutionRpc<N>>(
Path(address): Path<Address>,
Query(AccountProofQuery {
include_code,
storage_slots,
block,
}): Query<AccountProofQuery>,
State(ApiState { api_service }): State<ApiState<N, R>>,
) -> Response<AccountResponse> {
api_service
.get_account(address, &storage_slots, block)
.get_account(address, &storage_slots, block, include_code)
.await
.map(Json)
.map_err(map_server_err)
Expand Down Expand Up @@ -184,6 +187,17 @@ pub async fn get_chain_id<N: NetworkSpec, R: ExecutionRpc<N>>(
.map_err(map_server_err)
}

pub async fn get_block<N: NetworkSpec, R: ExecutionRpc<N>>(
Path(block_id): Path<BlockId>,
State(ApiState { api_service }): State<ApiState<N, R>>,
) -> Response<Option<N::BlockResponse>> {
api_service
.get_block(block_id)
.await
.map(Json)
.map_err(map_server_err)
}

pub async fn get_block_receipts<N: NetworkSpec, R: ExecutionRpc<N>>(
Path(block_id): Path<BlockId>,
State(ApiState { api_service }): State<ApiState<N, R>>,
Expand Down
3 changes: 2 additions & 1 deletion verifiable-api/server/bin/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ pub fn build_router<N: NetworkSpec, R: ExecutionRpc<N>>() -> Router<ApiState<N,
"/eth/v1",
Router::new()
.route("/chain_id", get(handlers::get_chain_id))
.route("/block/{block_id}", get(handlers::get_block))
.route(
"/block_receipts/{block_id}",
"/block/{block_id}/receipts",
get(handlers::get_block_receipts),
)
.route(
Expand Down
Loading

0 comments on commit 77dbd28

Please sign in to comment.