Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.

Commit 8aa831e

Browse files
authored
feat: Add get_proof RPC (#205)
1 parent 24e100b commit 8aa831e

File tree

2 files changed

+62
-3
lines changed

2 files changed

+62
-3
lines changed

bus-mapping/src/eth_types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use crate::evm::{memory::Memory, stack::Stack, storage::Storage};
44
use crate::evm::{Gas, GasCost, OpcodeId, ProgramCounter};
55
use ethers_core::types;
66
pub use ethers_core::types::{
7-
transaction::response::Transaction, Address, Block, Bytes, H160, H256,
8-
U256, U64,
7+
transaction::response::Transaction, Address, Block, Bytes,
8+
EIP1186ProofResponse, H160, H256, U256, U64,
99
};
1010
use pairing::arithmetic::FieldExt;
1111
use serde::{de, Deserialize};

bus-mapping/src/rpc.rs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
//! query a Geth node in order to get a Block, Tx or Trace info.
33
44
use crate::eth_types::{
5-
Block, GethExecTrace, Hash, ResultGethExecTraces, Transaction, U64,
5+
Address, Block, EIP1186ProofResponse, GethExecTrace, Hash,
6+
ResultGethExecTraces, Transaction, Word, U64,
67
};
78
use crate::Error;
89
use ethers_providers::JsonRpcClient;
@@ -119,6 +120,24 @@ impl<P: JsonRpcClient> GethClient<P> {
119120
.map_err(|e| Error::JSONRpcError(e.into()))?;
120121
Ok(resp.0.into_iter().map(|step| step.result).collect())
121122
}
123+
124+
/// Calls `eth_getProof` via JSON-RPC returning a [`EIP1186ProofResponse`]
125+
/// returning the account and storage-values of the specified
126+
/// account including the Merkle-proof.
127+
pub async fn get_proof(
128+
&self,
129+
account: Address,
130+
keys: Vec<Word>,
131+
block_num: BlockNumber,
132+
) -> Result<EIP1186ProofResponse, Error> {
133+
let account = serialize(&account);
134+
let keys = serialize(&keys);
135+
let num = block_num.serialize();
136+
self.0
137+
.request("eth_getProof", [account, keys, num])
138+
.await
139+
.map_err(|e| Error::JSONRpcError(e.into()))
140+
}
122141
}
123142

124143
#[cfg(test)]
@@ -199,4 +218,44 @@ mod rpc_tests {
199218
);
200219
assert!(!trace_by_hash[0].struct_logs.is_empty());
201220
}
221+
222+
// The test is ignored as the values used depend on the Geth instance used
223+
// each time you run the tests. And we can't assume that everyone will
224+
// have a Geth client synced with mainnet to have unified "test-vectors".
225+
#[ignore]
226+
#[tokio::test]
227+
async fn test_get_proof() {
228+
let transport = Http::new(Url::parse("http://localhost:8545").unwrap());
229+
let prov = GethClient::new(transport);
230+
231+
let address =
232+
Address::from_str("0x7F0d15C7FAae65896648C8273B6d7E43f58Fa842")
233+
.unwrap();
234+
let keys = vec![Word::from_str("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").unwrap()];
235+
let proof = prov
236+
.get_proof(address, keys, BlockNumber::Latest)
237+
.await
238+
.unwrap();
239+
const TARGET_PROOF: &str = r#"{
240+
"address": "0x7f0d15c7faae65896648c8273b6d7e43f58fa842",
241+
"accountProof": [
242+
"0xf873a12050fb4d3174ec89ef969c09fd4391602169760fb005ad516f5d172cbffb80e955b84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
243+
],
244+
"balance": "0x0",
245+
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
246+
"nonce": "0x0",
247+
"storageHash": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
248+
"storageProof": [
249+
{
250+
"key": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
251+
"value": "0x0",
252+
"proof": []
253+
}
254+
]
255+
}"#;
256+
assert!(
257+
serde_json::from_str::<EIP1186ProofResponse>(TARGET_PROOF).unwrap()
258+
== proof
259+
);
260+
}
202261
}

0 commit comments

Comments
 (0)