@@ -8,7 +8,8 @@ mod merkle_verifier;
88// TODO(xqft): check sizes
99const MAX_PROOF_SIZE : usize = 16 * 1024 ;
1010const MAX_PUB_INPUT_SIZE : usize = 6 * 1024 ;
11- const HASH_SIZE : usize = 32 ;
11+ const MINA_HASH_SIZE : usize = 32 ;
12+ const KECCAK_HASH_SIZE : usize = 32 ;
1213
1314#[ no_mangle]
1415pub extern "C" fn verify_account_inclusion_ffi (
@@ -22,7 +23,7 @@ pub extern "C" fn verify_account_inclusion_ffi(
2223 // and validated in this verifier. A smart contract could implement Poseidon
2324 // and hash the data itself but it's prohibitively expensive.
2425
25- let ( merkle_root, account_hash) =
26+ let ( merkle_root, account_hash, _account_id_hash ) =
2627 match parse_pub_inputs ( & public_input_bytes[ ..public_input_len] ) {
2728 Ok ( pub_inputs) => pub_inputs,
2829 Err ( err) => {
@@ -39,36 +40,58 @@ pub extern "C" fn verify_account_inclusion_ffi(
3940 }
4041 } ;
4142
43+ // TODO(xqft): when the needed account GraphQL query is done, do:
44+ // 1. send encoded account as part of the proof
45+ // 2. define account_id from encoded account.
46+ // 2. assert keccak256(account_id) == account_id_hash
47+
4248 verify_merkle_proof ( account_hash, merkle_proof, merkle_root)
4349}
4450
45- pub fn parse_hash ( pub_inputs : & [ u8 ] , offset : & mut usize ) -> Result < Fp , String > {
51+ fn parse_mina_hash ( pub_inputs : & [ u8 ] , offset : & mut usize ) -> Result < Fp , String > {
4652 let hash = pub_inputs
47- . get ( * offset..* offset + HASH_SIZE )
48- . ok_or ( "Failed to slice candidate hash" . to_string ( ) )
53+ . get ( * offset..* offset + MINA_HASH_SIZE )
54+ . ok_or ( "Failed to slice Mina hash" . to_string ( ) )
4955 . and_then ( |bytes| Fp :: from_bytes ( bytes) . map_err ( |err| err. to_string ( ) ) ) ?;
5056
51- * offset += HASH_SIZE ;
57+ * offset += MINA_HASH_SIZE ;
58+
59+ Ok ( hash)
60+ }
61+
62+ fn parse_keccak256_hash (
63+ pub_inputs : & [ u8 ] ,
64+ offset : & mut usize ,
65+ ) -> Result < [ u8 ; KECCAK_HASH_SIZE ] , String > {
66+ let mut hash = [ 0 ; KECCAK_HASH_SIZE ] ;
67+ hash. copy_from_slice (
68+ pub_inputs
69+ . get ( * offset..* offset + KECCAK_HASH_SIZE )
70+ . ok_or ( "Failed to slice keccak hash" . to_string ( ) ) ?,
71+ ) ;
72+
73+ * offset += KECCAK_HASH_SIZE ;
5274
5375 Ok ( hash)
5476}
5577
56- pub fn parse_pub_inputs ( pub_inputs : & [ u8 ] ) -> Result < ( Fp , Fp ) , String > {
78+ fn parse_pub_inputs ( pub_inputs : & [ u8 ] ) -> Result < ( Fp , Fp , [ u8 ; KECCAK_HASH_SIZE ] ) , String > {
5779 let mut offset = 0 ;
5880
59- let merkle_root = parse_hash ( pub_inputs, & mut offset) ?;
60- let account_hash = parse_hash ( pub_inputs, & mut offset) ?;
81+ let merkle_root = parse_mina_hash ( pub_inputs, & mut offset) ?;
82+ let account_hash = parse_mina_hash ( pub_inputs, & mut offset) ?;
83+ let account_id_hash = parse_keccak256_hash ( & pub_inputs, & mut offset) ?;
6184
62- Ok ( ( merkle_root, account_hash) )
85+ Ok ( ( merkle_root, account_hash, account_id_hash ) )
6386}
6487
65- pub fn parse_proof ( proof_bytes : & [ u8 ] ) -> Result < Vec < MerklePath > , String > {
66- let merkle_path_bytes = proof_bytes. chunks_exact ( HASH_SIZE + 1 ) ;
88+ fn parse_proof ( proof_bytes : & [ u8 ] ) -> Result < Vec < MerklePath > , String > {
89+ let merkle_path_bytes = proof_bytes. chunks_exact ( MINA_HASH_SIZE + 1 ) ;
6790
6891 if !merkle_path_bytes. remainder ( ) . is_empty ( ) {
6992 return Err ( format ! (
7093 "Merkle path bytes not a multiple of HASH_SIZE + 1 ({})" ,
71- HASH_SIZE + 1
94+ MINA_HASH_SIZE + 1
7295 ) ) ;
7396 }
7497
0 commit comments