@@ -4,7 +4,7 @@ use crate::{
44} ;
55use ethers:: {
66 providers:: { Http , Middleware , Provider } ,
7- types:: Filter ,
7+ types:: { Filter , Log } ,
88} ;
99use lambdaworks_crypto:: merkle_tree:: { merkle:: MerkleTree , traits:: IsMerkleTreeBackend } ;
1010use sha3:: { Digest , Keccak256 } ;
@@ -109,9 +109,63 @@ pub async fn is_proof_verified_in_aggregation_mode(
109109 beacon_client_url : String ,
110110 from_block : Option < u64 > ,
111111) -> Result < [ u8 ; 32 ] , ProofVerificationAggModeError > {
112+ let logs = get_aggregated_proofs_logs ( network, eth_rpc_url. clone ( ) , from_block) . await ?;
113+
114+ for log in logs {
115+ let Ok ( ( merkle_root, leaves) ) =
116+ get_blob_data_from_log ( eth_rpc_url. clone ( ) , beacon_client_url. clone ( ) , log) . await
117+ else {
118+ continue ;
119+ } ;
120+
121+ let leaves: Vec < Hash32 > = leaves. iter ( ) . map ( |leaf| Hash32 ( * leaf) ) . collect ( ) ;
122+ let merkle_tree: MerkleTree < Hash32 > = MerkleTree :: build ( & leaves) . unwrap ( ) ;
123+
124+ if leaves. contains ( & Hash32 ( verification_data. commitment ( ) ) ) {
125+ return if merkle_tree. root == merkle_root {
126+ Ok ( merkle_root)
127+ } else {
128+ Err ( ProofVerificationAggModeError :: UnmatchedBlobAndEventMerkleRoot )
129+ } ;
130+ }
131+ }
132+
133+ Err ( ProofVerificationAggModeError :: ProofNotFoundInLogs )
134+ }
135+
136+ pub async fn get_merkle_path_for_proof (
137+ network : Network ,
138+ eth_rpc_url : String ,
139+ beacon_client_url : String ,
140+ from_block : Option < u64 > ,
141+ proof_commitment : [ u8 ; 32 ] ,
142+ ) -> Result < Option < Vec < [ u8 ; 32 ] > > , ProofVerificationAggModeError > {
143+ let logs = get_aggregated_proofs_logs ( network, eth_rpc_url. clone ( ) , from_block) . await ?;
144+
145+ for log in logs {
146+ let ( _merkle_root, leaves) =
147+ get_blob_data_from_log ( eth_rpc_url. clone ( ) , beacon_client_url. clone ( ) , log) . await ?;
148+
149+ let leaves: Vec < Hash32 > = leaves. iter ( ) . map ( |leaf| Hash32 ( * leaf) ) . collect ( ) ;
150+ let merkle_tree: MerkleTree < Hash32 > = MerkleTree :: build ( & leaves) . unwrap ( ) ;
151+
152+ let Some ( pos) = leaves. iter ( ) . position ( |p| p. 0 == proof_commitment) else {
153+ continue ;
154+ } ;
155+
156+ return Ok ( Some ( merkle_tree. get_proof_by_pos ( pos) . unwrap ( ) . merkle_path ) ) ;
157+ }
158+
159+ Ok ( None )
160+ }
161+
162+ async fn get_aggregated_proofs_logs (
163+ network : Network ,
164+ eth_rpc_url : String ,
165+ from_block : Option < u64 > ,
166+ ) -> Result < Vec < Log > , ProofVerificationAggModeError > {
112167 let eth_rpc_provider = Provider :: < Http > :: try_from ( eth_rpc_url)
113168 . map_err ( |e| ProofVerificationAggModeError :: EthereumProviderError ( e. to_string ( ) ) ) ?;
114- let beacon_client = BeaconClient :: new ( beacon_client_url) ;
115169
116170 let from_block = match from_block {
117171 Some ( from_block) => from_block,
@@ -132,76 +186,73 @@ pub async fn is_proof_verified_in_aggregation_mode(
132186 . event ( "AggregatedProofVerified(bytes32,bytes32)" )
133187 . from_block ( from_block) ;
134188
135- let logs = eth_rpc_provider. get_logs ( & filter) . await . unwrap ( ) ;
136- for log in logs {
137- // First 32 bytes of the data are the bytes of the blob versioned hash
138- let blob_versioned_hash: [ u8 ; 32 ] = log. data [ 0 ..32 ]
139- . try_into ( )
140- . map_err ( |_| ProofVerificationAggModeError :: EventDecoding ) ?;
141-
142- // Event is indexed by merkle root
143- let merkle_root = log. topics [ 1 ] . 0 ;
144-
145- // Block Number shouldn't be empty, in case it is,
146- // there is a problem with this log, and we skip it
147- // This same logic is replicated for other checks.
148- let Some ( block_number) = log. block_number else {
149- continue ;
150- } ;
189+ Ok ( eth_rpc_provider. get_logs ( & filter) . await . unwrap ( ) )
190+ }
151191
152- let Some ( block) = eth_rpc_provider
153- . get_block ( block_number. as_u64 ( ) )
154- . await
155- . map_err ( |e| ProofVerificationAggModeError :: EthereumProviderError ( e. to_string ( ) ) ) ?
156- else {
157- continue ;
158- } ;
192+ async fn get_blob_data_from_log (
193+ eth_rpc_url : String ,
194+ beacon_client_url : String ,
195+ log : Log ,
196+ ) -> Result < ( [ u8 ; 32 ] , Vec < [ u8 ; 32 ] > ) , ProofVerificationAggModeError > {
197+ let eth_rpc_provider = Provider :: < Http > :: try_from ( eth_rpc_url)
198+ . map_err ( |e| ProofVerificationAggModeError :: EthereumProviderError ( e. to_string ( ) ) ) ?;
199+ let beacon_client = BeaconClient :: new ( beacon_client_url) ;
159200
160- let Some ( beacon_parent_root) = block. parent_beacon_block_root else {
161- continue ;
162- } ;
201+ // First 32 bytes of the data are the bytes of the blob versioned hash
202+ let blob_versioned_hash: [ u8 ; 32 ] = log. data [ 0 ..32 ]
203+ . try_into ( )
204+ . map_err ( |_| ProofVerificationAggModeError :: EventDecoding ) ?;
163205
164- let Some ( beacon_block) = beacon_client
165- . get_block_header_from_parent_hash ( beacon_parent_root. 0 )
166- . await
167- . map_err ( ProofVerificationAggModeError :: BeaconClient ) ?
168- else {
169- continue ;
170- } ;
206+ // Event is indexed by merkle root
207+ let merkle_root = log. topics [ 1 ] . 0 ;
171208
172- let slot: u64 = beacon_block
173- . header
174- . message
175- . slot
176- . parse ( )
177- . expect ( "Slot to be parsable number" ) ;
178-
179- let Some ( blob_data) = beacon_client
180- . get_blob_by_versioned_hash ( slot, blob_versioned_hash)
181- . await
182- . map_err ( ProofVerificationAggModeError :: BeaconClient ) ?
183- else {
184- continue ;
185- } ;
209+ // Block Number shouldn't be empty, in case it is,
210+ // there is a problem with this log, and we skip it
211+ // This same logic is replicated for other checks.
212+ let Some ( block_number) = log. block_number else {
213+ return Err ( ProofVerificationAggModeError :: EventDecoding ) ;
214+ } ;
186215
187- let blob_bytes =
188- hex :: decode ( blob_data . blob . replace ( "0x" , "" ) ) . expect ( "A valid hex encoded data" ) ;
189- let proof_commitments : Vec < Hash32 > = decoded_blob ( blob_bytes )
190- . iter ( )
191- . map ( |p| Hash32 ( * p ) )
192- . collect ( ) ;
193- let merkle_tree : MerkleTree < Hash32 > = MerkleTree :: build ( & proof_commitments ) . unwrap ( ) ;
216+ let Some ( block ) = eth_rpc_provider
217+ . get_block ( block_number . as_u64 ( ) )
218+ . await
219+ . map_err ( |e| ProofVerificationAggModeError :: EthereumProviderError ( e . to_string ( ) ) ) ?
220+ else {
221+ return Err ( ProofVerificationAggModeError :: EventDecoding ) ;
222+ } ;
194223
195- if proof_commitments. contains ( & Hash32 ( verification_data. commitment ( ) ) ) {
196- return if merkle_tree. root == merkle_root {
197- Ok ( merkle_root)
198- } else {
199- Err ( ProofVerificationAggModeError :: UnmatchedBlobAndEventMerkleRoot )
200- } ;
201- }
202- }
224+ let Some ( beacon_parent_root) = block. parent_beacon_block_root else {
225+ return Err ( ProofVerificationAggModeError :: EventDecoding ) ;
226+ } ;
203227
204- Err ( ProofVerificationAggModeError :: ProofNotFoundInLogs )
228+ let Some ( beacon_block) = beacon_client
229+ . get_block_header_from_parent_hash ( beacon_parent_root. 0 )
230+ . await
231+ . map_err ( ProofVerificationAggModeError :: BeaconClient ) ?
232+ else {
233+ return Err ( ProofVerificationAggModeError :: EventDecoding ) ;
234+ } ;
235+
236+ let slot: u64 = beacon_block
237+ . header
238+ . message
239+ . slot
240+ . parse ( )
241+ . expect ( "Slot to be parsable number" ) ;
242+
243+ let Some ( blob_data) = beacon_client
244+ . get_blob_by_versioned_hash ( slot, blob_versioned_hash)
245+ . await
246+ . map_err ( ProofVerificationAggModeError :: BeaconClient ) ?
247+ else {
248+ return Err ( ProofVerificationAggModeError :: EventDecoding ) ;
249+ } ;
250+
251+ let blob_bytes =
252+ hex:: decode ( blob_data. blob . replace ( "0x" , "" ) ) . expect ( "A valid hex encoded data" ) ;
253+ let proof_commitments = decoded_blob ( blob_bytes) ;
254+
255+ Ok ( ( merkle_root, proof_commitments) )
205256}
206257
207258fn decoded_blob ( blob_data : Vec < u8 > ) -> Vec < [ u8 ; 32 ] > {
0 commit comments