Skip to content

Commit aa7f092

Browse files
committed
impl more methods
1 parent 821965b commit aa7f092

File tree

9 files changed

+176
-29
lines changed

9 files changed

+176
-29
lines changed

core/src/execution/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::collections::{HashMap, HashSet};
22

33
use alloy::consensus::BlockHeader;
4+
use alloy::eips::BlockId;
45
use alloy::network::primitives::HeaderResponse;
56
use alloy::network::{BlockResponse, ReceiptResponse};
67
use alloy::primitives::{keccak256, Address, B256, U256};
@@ -206,6 +207,7 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>> ExecutionClient<N, R> {
206207
let receipt = receipt.unwrap();
207208

208209
let block_number = receipt.block_number().unwrap();
210+
let block_id = BlockId::from(block_number);
209211
let tag = BlockTag::Number(block_number);
210212

211213
let block = self.state.get_block(tag).await;
@@ -218,7 +220,7 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>> ExecutionClient<N, R> {
218220
// Fetch all receipts in block, check root and inclusion
219221
let receipts = self
220222
.rpc
221-
.get_block_receipts(tag)
223+
.get_block_receipts(block_id)
222224
.await?
223225
.ok_or(eyre::eyre!(ExecutionError::NoReceiptsForBlock(tag)))?;
224226

@@ -251,12 +253,11 @@ impl<N: NetworkSpec, R: ExecutionRpc<N>> ExecutionClient<N, R> {
251253
} else {
252254
return Ok(None);
253255
};
254-
255-
let tag = BlockTag::Number(block.header().number());
256+
let block_id = BlockId::from(block.header().number());
256257

257258
let receipts = self
258259
.rpc
259-
.get_block_receipts(tag)
260+
.get_block_receipts(block_id)
260261
.await?
261262
.ok_or(eyre::eyre!(ExecutionError::NoReceiptsForBlock(tag)))?;
262263

core/src/execution/rpc/http_rpc.rs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -121,17 +121,10 @@ impl<N: NetworkSpec> ExecutionRpc<N> for HttpRpc<N> {
121121
Ok(receipt)
122122
}
123123

124-
async fn get_block_receipts(&self, block: BlockTag) -> Result<Option<Vec<N::ReceiptResponse>>> {
125-
let block = match block {
126-
BlockTag::Latest => BlockNumberOrTag::Latest,
127-
BlockTag::Finalized => BlockNumberOrTag::Finalized,
128-
BlockTag::Number(num) => BlockNumberOrTag::Number(num),
129-
};
130-
131-
let block_id = BlockId::from(block);
124+
async fn get_block_receipts(&self, block: BlockId) -> Result<Option<Vec<N::ReceiptResponse>>> {
132125
let receipts = self
133126
.provider
134-
.get_block_receipts(block_id)
127+
.get_block_receipts(block)
135128
.await
136129
.map_err(|e| RpcError::new("get_block_receipts", e))?;
137130

core/src/execution/rpc/mock_rpc.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,7 @@ impl<N: NetworkSpec> ExecutionRpc<N> for MockRpc {
5858
Ok(serde_json::from_str(&receipt)?)
5959
}
6060

61-
async fn get_block_receipts(
62-
&self,
63-
_block: BlockTag,
64-
) -> Result<Option<Vec<N::ReceiptResponse>>> {
61+
async fn get_block_receipts(&self, _block: BlockId) -> Result<Option<Vec<N::ReceiptResponse>>> {
6562
let receipts = read_to_string(self.path.join("receipts.json"))?;
6663
Ok(serde_json::from_str(&receipts)?)
6764
}

core/src/execution/rpc/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub trait ExecutionRpc<N: NetworkSpec>: Send + Clone + Sync + 'static {
3636
async fn get_code(&self, address: Address, block: u64) -> Result<Vec<u8>>;
3737
async fn send_raw_transaction(&self, bytes: &[u8]) -> Result<B256>;
3838
async fn get_transaction_receipt(&self, tx_hash: B256) -> Result<Option<N::ReceiptResponse>>;
39-
async fn get_block_receipts(&self, block: BlockTag) -> Result<Option<Vec<N::ReceiptResponse>>>;
39+
async fn get_block_receipts(&self, block: BlockId) -> Result<Option<Vec<N::ReceiptResponse>>>;
4040
async fn get_transaction(&self, tx_hash: B256) -> Result<Option<N::TransactionResponse>>;
4141
async fn get_logs(&self, filter: &Filter) -> Result<Vec<Log>>;
4242
async fn get_filter_changes(&self, filter_id: U256) -> Result<FilterChanges>;

verifiable-api/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44

55
| Ethereum JSON-RPC Method | Helios Verifiable API Endpoint |
66
|--------------------------------|-------------------------------------------------------------------------|
7+
| `eth_getProof` | `/eth/v1/proof/account/{address}?block={tag_or_hash_number}` |
78
| `eth_getBalance` | `/eth/v1/proof/balance/{address}?block={tag_or_hash_number}` |
89
| `eth_getTransactionCount` | `/eth/v1/proof/transaction_count/{address}?block={tag_or_hash_number}` |
910
| `eth_getCode` | `/eth/v1/proof/code/{address}?block={tag_or_hash_number}` |
1011
| `eth_getStorageAt` | `/eth/v1/proof/storage/{address}/{slot}?block={tag_or_hash_number}` |
12+
| `eth_getBlockReceipts` | `/eth/v1/proof/block_receipts/{block}` |
1113
| `eth_getTransactionReceipt` | `/eth/v1/proof/tx_receipt/{tx_hash}` |
12-
| `eth_getFilterLogs` | `/eth/v1/proof/filter_logs/{filter_id}` |
14+
| `eth_getFilterLogs` | `/eth/v1/proof/filter_logs/{filter_id}` |
15+
| `eth_getFilterChanges` | `/eth/v1/proof/filter_changes/{filter_id}` |

verifiable-api/bin/handlers.rs

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use alloy::{
88
eips::BlockNumberOrTag,
99
network::{BlockResponse, ReceiptResponse},
1010
primitives::{Address, B256, U256},
11-
rpc::types::{BlockId, BlockTransactionsKind, Log},
11+
rpc::types::{BlockId, BlockTransactionsKind, FilterChanges, Log},
1212
};
1313
use axum::{
1414
extract::{Path, Query, State},
@@ -20,7 +20,7 @@ use futures::future::try_join_all;
2020
use serde::{de::DeserializeOwned, Deserialize, Serialize};
2121
use serde_json::json;
2222

23-
use helios_core::{execution::rpc::ExecutionRpc, network_spec::NetworkSpec, types::BlockTag};
23+
use helios_core::{execution::rpc::ExecutionRpc, network_spec::NetworkSpec};
2424
use helios_verifiable_api::{proof::create_receipt_proof, rpc_client::ExecutionClient, types::*};
2525

2626
use crate::ApiState;
@@ -42,6 +42,34 @@ pub struct BlockQuery {
4242
block: Option<BlockId>,
4343
}
4444

45+
#[derive(Deserialize)]
46+
pub struct AccountProofQuery {
47+
pub block: Option<BlockId>,
48+
pub storage_keys: Vec<B256>,
49+
}
50+
51+
/// This method returns the account proof for a given address.
52+
///
53+
/// Replaces the `eth_getProof` RPC method.
54+
pub async fn get_account_proof<N: NetworkSpec, R: ExecutionRpc<N>>(
55+
Path(address): Path<Address>,
56+
Query(AccountProofQuery {
57+
block,
58+
storage_keys,
59+
}): Query<AccountProofQuery>,
60+
State(ApiState { execution_client }): State<ApiState<N, R>>,
61+
) -> Response<GetAccountProofResponse> {
62+
let block = block.unwrap_or(BlockId::latest());
63+
64+
let proof = execution_client
65+
.rpc
66+
.get_proof(address, &storage_keys, block)
67+
.await
68+
.map_err(map_server_err)?;
69+
70+
Ok(Json(proof))
71+
}
72+
4573
/// This method returns the balance of an account for a given address,
4674
/// along with the Merkle proof of the account's inclusion in the state trie.
4775
///
@@ -178,7 +206,7 @@ pub async fn get_storage_at<N: NetworkSpec, R: ExecutionRpc<N>>(
178206

179207
let proof = execution_client
180208
.rpc
181-
.get_proof(address, &[storage_slot.into()], block)
209+
.get_proof(address, &[storage_slot], block)
182210
.await
183211
.map_err(map_server_err)?;
184212

@@ -204,6 +232,25 @@ pub async fn get_storage_at<N: NetworkSpec, R: ExecutionRpc<N>>(
204232
}))
205233
}
206234

235+
/// This method returns all transaction receipts for a given block.
236+
///
237+
/// Replaces the `eth_getBlockReceipts` RPC method.
238+
pub async fn get_block_receipts<N: NetworkSpec, R: ExecutionRpc<N>>(
239+
Path(block): Path<Option<BlockId>>,
240+
State(ApiState { execution_client }): State<ApiState<N, R>>,
241+
) -> Response<GetBlockReceiptsResponse<N>> {
242+
let block = block.unwrap_or(BlockId::latest());
243+
244+
let receipts = execution_client
245+
.rpc
246+
.get_block_receipts(block)
247+
.await
248+
.map_err(map_server_err)?
249+
.unwrap_or(vec![]);
250+
251+
Ok(Json(receipts))
252+
}
253+
207254
/// This method returns the receipt of a transaction along with a Merkle proof of its inclusion.
208255
///
209256
/// Replaces the `eth_getTransactionReceipt` RPC method.
@@ -225,7 +272,7 @@ pub async fn get_transaction_receipt<N: NetworkSpec, R: ExecutionRpc<N>>(
225272

226273
let receipts = execution_client
227274
.rpc
228-
.get_block_receipts(BlockTag::Number(receipt.block_number().unwrap()))
275+
.get_block_receipts(BlockId::from(receipt.block_number().unwrap()))
229276
.await
230277
.map_err(map_server_err)?
231278
.ok_or_else(|| {
@@ -270,6 +317,41 @@ pub async fn get_filter_logs<N: NetworkSpec, R: ExecutionRpc<N>>(
270317
}))
271318
}
272319

320+
/// This method returns the changes since the last poll for a given filter id.
321+
/// If filter is of logs type, then corresponding to each log,
322+
/// it also returns the transaction receipt and a Merkle proof of its inclusion..
323+
///
324+
/// Replaces the `eth_getFilterChanges` RPC method.
325+
pub async fn get_filter_changes<N: NetworkSpec, R: ExecutionRpc<N>>(
326+
Path(filter_id): Path<U256>,
327+
State(ApiState { execution_client }): State<ApiState<N, R>>,
328+
) -> Response<GetFilterChangesResponse<N>> {
329+
let filter_changes = execution_client
330+
.rpc
331+
.get_filter_changes(filter_id)
332+
.await
333+
.map_err(map_server_err)?;
334+
335+
Ok(Json(match filter_changes {
336+
FilterChanges::Logs(logs) => {
337+
// Create receipt proofs for each log
338+
let receipt_proofs = create_receipt_proofs_for_logs(&logs, execution_client)
339+
.await
340+
.map_err(map_server_err)?;
341+
342+
GetFilterChangesResponse::Logs(GetFilterLogsResponse {
343+
logs,
344+
receipt_proofs,
345+
})
346+
}
347+
FilterChanges::Hashes(hashes) => GetFilterChangesResponse::Hashes(hashes),
348+
FilterChanges::Empty => GetFilterChangesResponse::Hashes(vec![]),
349+
FilterChanges::Transactions(txs) => GetFilterChangesResponse::Hashes(
350+
txs.into_iter().map(|t| t.inner.tx_hash().clone()).collect(),
351+
),
352+
}))
353+
}
354+
273355
async fn create_receipt_proofs_for_logs<N: NetworkSpec, R: ExecutionRpc<N>>(
274356
logs: &[Log],
275357
execution_client: Arc<ExecutionClient<N, R>>,
@@ -284,8 +366,8 @@ async fn create_receipt_proofs_for_logs<N: NetworkSpec, R: ExecutionRpc<N>>(
284366
let blocks_receipts_fut = block_nums.into_iter().map(|block_num| {
285367
let execution_client = Arc::clone(&execution_client);
286368
async move {
287-
let tag = BlockTag::Number(block_num);
288-
let receipts = execution_client.rpc.get_block_receipts(tag).await?;
369+
let block_id = BlockId::from(block_num);
370+
let receipts = execution_client.rpc.get_block_receipts(block_id).await?;
289371
receipts
290372
.ok_or_eyre("No receipts found for the block")
291373
.map(|receipts| (block_num, receipts))

verifiable-api/bin/router.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,23 @@ pub fn build_router<N: NetworkSpec, R: ExecutionRpc<N>>() -> Router<ApiState<N,
88
Router::new().nest(
99
"/eth/v1/proof",
1010
Router::new()
11+
.route("/account/{address}", get(handlers::get_account_proof))
1112
.route("/balance/{address}", get(handlers::get_balance))
1213
.route(
1314
"/transaction_count/{address}",
1415
get(handlers::get_transaction_count),
1516
)
1617
.route("/code/{address}", get(handlers::get_code))
1718
.route("/storage/{address}/{slot}", get(handlers::get_storage_at))
19+
.route("/block_receipts/{block}", get(handlers::get_block_receipts))
1820
.route(
1921
"/tx_receipt/{tx_hash}",
2022
get(handlers::get_transaction_receipt),
2123
)
22-
.route("/filter_logs/{filter_id}", get(handlers::get_filter_logs)),
24+
.route("/filter_logs/{filter_id}", get(handlers::get_filter_logs))
25+
.route(
26+
"/filter_changes/{filter_id}",
27+
get(handlers::get_filter_changes),
28+
),
2329
)
2430
}

verifiable-api/src/api_client.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ use crate::types::*;
1212

1313
#[async_trait]
1414
pub trait VerifiableApi<N: NetworkSpec> {
15+
async fn get_account(
16+
&self,
17+
address: Address,
18+
block: Option<BlockId>,
19+
) -> Result<GetAccountProofResponse, Error>;
1520
async fn get_balance(
1621
&self,
1722
address: Address,
@@ -33,11 +38,19 @@ pub trait VerifiableApi<N: NetworkSpec> {
3338
key: U256,
3439
block: Option<BlockId>,
3540
) -> Result<GetStorageAtResponse, Error>;
41+
async fn get_block_receipts(
42+
&self,
43+
block: BlockId,
44+
) -> Result<GetBlockReceiptsResponse<N>, Error>;
3645
async fn get_transaction_receipt(
3746
&self,
3847
tx_hash: B256,
3948
) -> Result<GetTransactionReceiptResponse<N>, Error>;
4049
async fn get_filter_logs(&self, filter_id: U256) -> Result<GetFilterLogsResponse<N>, Error>;
50+
async fn get_filter_changes(
51+
&self,
52+
filter_id: U256,
53+
) -> Result<GetFilterChangesResponse<N>, Error>;
4154
}
4255

4356
pub struct VerifiableApiClient {
@@ -56,6 +69,22 @@ impl VerifiableApiClient {
5669

5770
#[async_trait]
5871
impl<N: NetworkSpec> VerifiableApi<N> for VerifiableApiClient {
72+
async fn get_account(
73+
&self,
74+
address: Address,
75+
block: Option<BlockId>,
76+
) -> Result<GetAccountProofResponse, Error> {
77+
let url = format!("{}/eth/v1/proof/account/{}", self.base_url, address);
78+
let response = self
79+
.client
80+
.get(&url)
81+
.query(&[("block", block)])
82+
.send()
83+
.await?;
84+
let response = response.json::<GetAccountProofResponse>().await?;
85+
Ok(response)
86+
}
87+
5988
async fn get_balance(
6089
&self,
6190
address: Address,
@@ -124,6 +153,16 @@ impl<N: NetworkSpec> VerifiableApi<N> for VerifiableApiClient {
124153
Ok(response)
125154
}
126155

156+
async fn get_block_receipts(
157+
&self,
158+
block: BlockId,
159+
) -> Result<GetBlockReceiptsResponse<N>, Error> {
160+
let url = format!("{}/eth/v1/proof/block_receipts/{}", self.base_url, block);
161+
let response = self.client.get(&url).send().await?;
162+
let response = response.json::<GetBlockReceiptsResponse<N>>().await?;
163+
Ok(response)
164+
}
165+
127166
async fn get_transaction_receipt(
128167
&self,
129168
tx_hash: B256,
@@ -140,4 +179,17 @@ impl<N: NetworkSpec> VerifiableApi<N> for VerifiableApiClient {
140179
let response = response.json::<GetFilterLogsResponse<N>>().await?;
141180
Ok(response)
142181
}
182+
183+
async fn get_filter_changes(
184+
&self,
185+
filter_id: U256,
186+
) -> Result<GetFilterChangesResponse<N>, Error> {
187+
let url = format!(
188+
"{}/eth/v1/proof/filter_changes/{}",
189+
self.base_url, filter_id
190+
);
191+
let response = self.client.get(&url).send().await?;
192+
let response = response.json::<GetFilterChangesResponse<N>>().await?;
193+
Ok(response)
194+
}
143195
}

0 commit comments

Comments
 (0)