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

Commit

Permalink
feat: Add get_proof RPC (#205)
Browse files Browse the repository at this point in the history
  • Loading branch information
spartucus authored Dec 2, 2021
1 parent 24e100b commit 8aa831e
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 3 deletions.
4 changes: 2 additions & 2 deletions bus-mapping/src/eth_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use crate::evm::{memory::Memory, stack::Stack, storage::Storage};
use crate::evm::{Gas, GasCost, OpcodeId, ProgramCounter};
use ethers_core::types;
pub use ethers_core::types::{
transaction::response::Transaction, Address, Block, Bytes, H160, H256,
U256, U64,
transaction::response::Transaction, Address, Block, Bytes,
EIP1186ProofResponse, H160, H256, U256, U64,
};
use pairing::arithmetic::FieldExt;
use serde::{de, Deserialize};
Expand Down
61 changes: 60 additions & 1 deletion bus-mapping/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
//! query a Geth node in order to get a Block, Tx or Trace info.

use crate::eth_types::{
Block, GethExecTrace, Hash, ResultGethExecTraces, Transaction, U64,
Address, Block, EIP1186ProofResponse, GethExecTrace, Hash,
ResultGethExecTraces, Transaction, Word, U64,
};
use crate::Error;
use ethers_providers::JsonRpcClient;
Expand Down Expand Up @@ -119,6 +120,24 @@ impl<P: JsonRpcClient> GethClient<P> {
.map_err(|e| Error::JSONRpcError(e.into()))?;
Ok(resp.0.into_iter().map(|step| step.result).collect())
}

/// Calls `eth_getProof` via JSON-RPC returning a [`EIP1186ProofResponse`]
/// returning the account and storage-values of the specified
/// account including the Merkle-proof.
pub async fn get_proof(
&self,
account: Address,
keys: Vec<Word>,
block_num: BlockNumber,
) -> Result<EIP1186ProofResponse, Error> {
let account = serialize(&account);
let keys = serialize(&keys);
let num = block_num.serialize();
self.0
.request("eth_getProof", [account, keys, num])
.await
.map_err(|e| Error::JSONRpcError(e.into()))
}
}

#[cfg(test)]
Expand Down Expand Up @@ -199,4 +218,44 @@ mod rpc_tests {
);
assert!(!trace_by_hash[0].struct_logs.is_empty());
}

// The test is ignored as the values used depend on the Geth instance used
// each time you run the tests. And we can't assume that everyone will
// have a Geth client synced with mainnet to have unified "test-vectors".
#[ignore]
#[tokio::test]
async fn test_get_proof() {
let transport = Http::new(Url::parse("http://localhost:8545").unwrap());
let prov = GethClient::new(transport);

let address =
Address::from_str("0x7F0d15C7FAae65896648C8273B6d7E43f58Fa842")
.unwrap();
let keys = vec![Word::from_str("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").unwrap()];
let proof = prov
.get_proof(address, keys, BlockNumber::Latest)
.await
.unwrap();
const TARGET_PROOF: &str = r#"{
"address": "0x7f0d15c7faae65896648c8273b6d7e43f58fa842",
"accountProof": [
"0xf873a12050fb4d3174ec89ef969c09fd4391602169760fb005ad516f5d172cbffb80e955b84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
],
"balance": "0x0",
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
"nonce": "0x0",
"storageHash": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"storageProof": [
{
"key": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"value": "0x0",
"proof": []
}
]
}"#;
assert!(
serde_json::from_str::<EIP1186ProofResponse>(TARGET_PROOF).unwrap()
== proof
);
}
}

0 comments on commit 8aa831e

Please sign in to comment.