diff --git a/ethereum/circuits/lib/src/account_with_storage_recursive.nr b/ethereum/circuits/lib/src/account_with_storage_recursive.nr new file mode 100644 index 00000000..11585de0 --- /dev/null +++ b/ethereum/circuits/lib/src/account_with_storage_recursive.nr @@ -0,0 +1,58 @@ +use crate::misc::{fragment::Fragment, types::{Address, Bytes32, ADDRESS_LENGTH, BYTES32_LENGTH}}; +use crate::serde::STORAGE_BLOCK_LEN; +use dep::std::verify_proof; +use crate::account_with_storage::StorageWithinBlock; +use dep::std::unsafe::zeroed; + +struct RecursiveProof { + key_hash: Field, + verification_key: [Field; 114], + proof: [Field; 93], +} + +global NUM_PUBLIC_INPUTS = 1 + 1 + ADDRESS_LENGTH + BYTES32_LENGTH + STORAGE_BLOCK_LEN; // chain_id + block_number + address + storage_key + public_return_inputs + +pub fn get_account_with_storage_recursive( + chain_id: Field, + block_number: u64, + address: Address, + storage_key: Bytes32 +) -> StorageWithinBlock<1> { + let (storage_within_block, RecursiveProof {key_hash, verification_key, proof}) = get_account_with_storage_recursive_unconstrained(chain_id, block_number, address, storage_key); + + let mut public_inputs: Fragment = Fragment::empty(); + public_inputs.push_back(chain_id); + public_inputs.push_back(block_number as Field); + public_inputs.extend_back(address.serialize()); + public_inputs.extend_back(storage_key.serialize()); + public_inputs.extend_back(storage_within_block.serialize()); + let public_inputs_array: [Field; NUM_PUBLIC_INPUTS] = public_inputs.to_array(); + + verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs_array.as_slice(), + key_hash + ); + + storage_within_block +} + +#[oracle(get_account_with_storage_recursive)] +unconstrained fn get_account_with_storage_recursive_oracle( + chain_id: Field, + block_number: u64, + address: Address, + storage_key: Bytes32 +) -> ([Field; STORAGE_BLOCK_LEN], RecursiveProof) {} + +unconstrained fn get_account_with_storage_recursive_unconstrained( + chain_id: Field, + block_number: u64, + address: Address, + storage_key: Bytes32 +) -> (StorageWithinBlock<1>, RecursiveProof) { + let (return_value_serialized, proof) = get_account_with_storage_recursive_oracle(chain_id, block_number, address, storage_key); + let return_value = StorageWithinBlock::deserialize(return_value_serialized); + (return_value, proof) +} diff --git a/ethereum/circuits/lib/src/account_with_storage_recursive_int_test.nr b/ethereum/circuits/lib/src/account_with_storage_recursive_int_test.nr new file mode 100644 index 00000000..fd7a5231 --- /dev/null +++ b/ethereum/circuits/lib/src/account_with_storage_recursive_int_test.nr @@ -0,0 +1,16 @@ +use crate::account_with_storage_recursive::{get_account_with_storage_recursive, RecursiveProof}; +use crate::account_with_storage::StorageWithinBlock; +use crate::fixtures::mainnet::paris::usdc_circle::{header::{number, hash}, account::{address, account} storage::{keys, values}}; +use crate::chain::ETHEREUM_MAINNET_ID; +use crate::misc::types::{Bytes32, Address}; +use dep::std::test::OracleMock; + +#[test] +fn success() { + let result = StorageWithinBlock { block_hash: hash, account, values }; + let recursive_proof = RecursiveProof { key_hash: 1, verification_key: [0; 114], proof: [0; 93] }; + + let _ = OracleMock::mock("get_account_with_storage_recursive").returns((result.serialize(), recursive_proof)); + + get_account_with_storage_recursive(ETHEREUM_MAINNET_ID, number, address, keys[0]); +} diff --git a/ethereum/circuits/lib/src/lib.nr b/ethereum/circuits/lib/src/lib.nr index 09c7cdf5..0b1f2edc 100644 --- a/ethereum/circuits/lib/src/lib.nr +++ b/ethereum/circuits/lib/src/lib.nr @@ -4,6 +4,8 @@ mod header; mod header_int_test; mod account_with_storage; mod account_with_storage_int_test; +mod account_with_storage_recursive; +mod account_with_storage_recursive_int_test; mod receipt; mod receipt_int_test; mod log; diff --git a/vlayer/ethereum/circuits/lib/src/token.nr b/vlayer/ethereum/circuits/lib/src/token.nr index 1ec16732..433c02e4 100644 --- a/vlayer/ethereum/circuits/lib/src/token.nr +++ b/vlayer/ethereum/circuits/lib/src/token.nr @@ -1,5 +1,6 @@ use dep::ethereum::{ - account_with_storage::get_account_with_storage, misc::types::{Address, Bytes32}, + account_with_storage::get_account_with_storage, + account_with_storage_recursive::get_account_with_storage_recursive, misc::types::{Address, Bytes32}, misc::bytes32::address_to_bytes32 }; use dep::std::field::bytes32_to_field; @@ -27,7 +28,7 @@ trait ERC20 { impl ERC20 for ERC20Token { fn get_balance(self, wallet_address: Address, block_number: u64) -> U128 { let storage_key = self.calculate_balance_storage_key(wallet_address); - let account = get_account_with_storage(self.chain_id, block_number, self.address, storage_key); + let account = get_account_with_storage_recursive(self.chain_id, block_number, self.address, storage_key); let balance = account.values[TOKEN_BALANCE_INDEX]; U128::from_integer(bytes32_to_field(balance)) diff --git a/vlayer/examples/circuits/is_dao_worthy/Verifier.toml b/vlayer/examples/circuits/is_dao_worthy/Verifier.toml index d7521d88..6b5c37d3 100644 --- a/vlayer/examples/circuits/is_dao_worthy/Verifier.toml +++ b/vlayer/examples/circuits/is_dao_worthy/Verifier.toml @@ -1 +1 @@ -block_number = 19000000 +block_number = "0x000000000000000000000000000000000000000000000000000000000121eac0"