@@ -13,96 +13,105 @@ pub enum ProofVerificationAggModeError {
1313 ProvingSystemNotSupportedInAggMode ,
1414 EthereumProviderError ( String ) ,
1515 BeaconClient ( BeaconClientError ) ,
16+ UnmatchedBlobAndEventMerkleRoot ,
17+ ProofNotFoundInLogs ,
18+ EventDecoding ,
1619}
1720
18- /// Given aligned verification data, it verifies if the proof was verified in the last aggregated proof
19- /// Currently, this in Beta mode so there isn't a way to know exactly to which proof it belongs
20- /// So currently we check if included in the last one and verify the merkle root commitment
21- /// The step by step verification consists of:
22- /// 1. Query the blob versioned hash of latest event from aligned proof aggregation service contract
23- /// 2. Get the beacon block via the block parent beacon root
24- /// 3. Fetch the blobs for that slot
25- /// 4. Filter the blob with the blob versioned hash
26- /// 5. Decode the blobs proofs
27- /// 6. Find if the proofs hash is inside the blob proofs
28- /// 7. Construct merkle root and verify it matches the one in the contract
21+ /// Given aligned verification data, this function checks whether a proof was included
22+ /// in the most recent aggregated proof and verifies the corresponding Merkle root commitment.
23+ ///
24+ /// Note: This functionality is currently in Beta. As a result, we cannot determine with certainty
25+ /// which specific aggregation a proof belongs to. Instead, we optimistically check the latest one.
26+ ///
27+ /// ⚠️ The `from` block used in the verification process must not be older than 18 days,
28+ /// as blobs expire after that period and will no longer be retrievable.
29+ ///
30+ /// The step-by-step verification process includes:
31+ /// 1. Querying the blob versioned hash from the latest event emitted by the aligned proof aggregation service contract
32+ /// 2. Retrieving the corresponding beacon block using the block’s parent beacon root
33+ /// 3. Fetching the blobs associated with that slot
34+ /// 4. Filtering the blob that matches the queried blob versioned hash
35+ /// 5. Decoding the blob to extract the proofs
36+ /// 6. Checking if the given proof hash exists within the blob’s proofs
37+ /// 7. Reconstructing the Merkle root and verifying it against the commitment stored in the contract
2938pub async fn is_proof_verified_in_aggregation_mode (
30- proof_hash : String ,
39+ proof_hash : [ u8 ; 32 ] ,
3140 network : Network ,
3241 eth_rpc_url : String ,
3342 beacon_client_url : String ,
3443 from_block : u64 ,
35- ) -> Result < bool , ProofVerificationAggModeError > {
36- // TODO: check if the from_block is past 18 days as the blob_data won't be available anymore
37-
44+ ) -> Result < [ u8 ; 32 ] , ProofVerificationAggModeError > {
3845 let eth_rpc_provider = Provider :: < Http > :: try_from ( eth_rpc_url)
3946 . map_err ( |e| ProofVerificationAggModeError :: EthereumProviderError ( e. to_string ( ) ) ) ?;
47+ let beacon_client = BeaconClient :: new ( beacon_client_url) ;
4048
4149 let filter = Filter :: new ( )
4250 . address ( network. get_aligned_proof_agg_service_address ( ) )
4351 . event ( "AggregatedProofVerified(bytes32,bytes32)" )
4452 . from_block ( from_block) ;
4553
46- let mut to_check: Vec < ( [ u8 ; 32 ] , [ u8 ; 32 ] , u64 ) > = vec ! [ ] ;
47-
4854 let logs = eth_rpc_provider. get_logs ( & filter) . await . unwrap ( ) ;
4955 for log in logs {
5056 let blob_versioned_hash: [ u8 ; 32 ] = log. data [ 0 ..32 ]
5157 . try_into ( )
52- . expect ( "Data has incorrect length" ) ;
53- let merkle_root = log. topics . get ( 1 ) . expect ( "to decode merkle root in index" ) . 0 ;
54-
55- to_check. push ( (
56- blob_versioned_hash,
57- merkle_root,
58- log. block_number . unwrap ( ) . 0 [ 0 ] ,
59- ) ) ;
60- }
61-
62- let beacon_client = BeaconClient :: new ( beacon_client_url) ;
58+ . map_err ( |_| ProofVerificationAggModeError :: EventDecoding ) ?;
59+ let merkle_root = log. topics [ 1 ] . 0 ;
60+ let Some ( block_number) = log. block_number else {
61+ continue ;
62+ } ;
6363
64- // Start checking each log and blob versioned hash
65- for ( blob_versioned_hash, merkle_root, block_number) in to_check {
66- let block = eth_rpc_provider
67- . get_block ( block_number)
64+ let Some ( block) = eth_rpc_provider
65+ . get_block ( block_number. as_u64 ( ) )
6866 . await
69- . unwrap ( )
70- . unwrap ( ) ;
71- let beacon_parent_root = block. parent_beacon_block_root . unwrap ( ) ;
67+ . map_err ( |e| ProofVerificationAggModeError :: EthereumProviderError ( e. to_string ( ) ) ) ?
68+ else {
69+ continue ;
70+ } ;
7271
73- let beacon_block = beacon_client
72+ let Some ( beacon_parent_root) = block. parent_beacon_block_root else {
73+ continue ;
74+ } ;
75+
76+ let Some ( beacon_block) = beacon_client
7477 . get_block_header_from_parent_hash ( beacon_parent_root. 0 )
7578 . await
7679 . map_err ( ProofVerificationAggModeError :: BeaconClient ) ?
77- . unwrap ( ) ;
80+ else {
81+ continue ;
82+ } ;
7883
79- let blob = beacon_client
84+ let Some ( blob) = beacon_client
8085 . get_blob_by_versioned_hash (
81- beacon_block. header . message . slot . parse ( ) . expect ( "a number" ) ,
86+ beacon_block
87+ . header
88+ . message
89+ . slot
90+ . parse ( )
91+ . expect ( "Slot to be parsable number" ) ,
8292 blob_versioned_hash,
8393 )
8494 . await
8595 . map_err ( ProofVerificationAggModeError :: BeaconClient ) ?
86- . unwrap ( ) ;
96+ else {
97+ continue ;
98+ } ;
8799
88100 let blob_data = hex:: decode ( blob. blob . replace ( "0x" , "" ) ) . expect ( "A valid hex encoded data" ) ;
89-
90101 let proof_hashes = decoded_blob ( blob_data) ;
91102
92- // decoded blob and get all leaves and see if it the has is inside
93- let proof_hash_bytes: [ u8 ; 32 ] = hex:: decode ( proof_hash. replace ( "0x" , "" ) )
94- . unwrap ( )
95- . try_into ( )
96- . unwrap ( ) ;
97-
98- if proof_hashes. contains ( & proof_hash_bytes) {
99- return Ok ( verify_blob_merkle_root ( proof_hashes, merkle_root) ) ;
103+ if proof_hashes. contains ( & proof_hash) {
104+ if verify_blob_merkle_root ( proof_hashes, merkle_root) {
105+ return Ok ( merkle_root) ;
106+ } else {
107+ return Err ( ProofVerificationAggModeError :: UnmatchedBlobAndEventMerkleRoot ) ;
108+ }
100109 } else {
101110 continue ;
102111 }
103112 }
104113
105- Ok ( false )
114+ return Err ( ProofVerificationAggModeError :: ProofNotFoundInLogs ) ;
106115}
107116
108117fn decoded_blob ( blob_data : Vec < u8 > ) -> Vec < [ u8 ; 32 ] > {
0 commit comments