11// Copyright 2023-, Semiotic AI, Inc.
22// SPDX-License-Identifier: Apache-2.0
33
4+ use std:: collections:: HashSet ;
5+
46use alloy_sol_types:: Eip712Domain ;
7+ use ethers:: types:: Signature ;
58use tokio:: sync:: RwLock ;
69
710use crate :: {
@@ -12,6 +15,8 @@ use crate::{
1215 Error , Result ,
1316} ;
1417
18+ use super :: ReceivedReceipt ;
19+
1520pub struct ReceiptAuditor < EA : EscrowAdapter , RCA : ReceiptChecksAdapter > {
1621 domain_separator : Eip712Domain ,
1722 escrow_adapter : EA ,
@@ -58,6 +63,25 @@ impl<EA: EscrowAdapter, RCA: ReceiptChecksAdapter> ReceiptAuditor<EA, RCA> {
5863 }
5964 }
6065
66+ pub async fn check_batch (
67+ & self ,
68+ receipt_check : & ReceiptCheck ,
69+ received_receipts : & mut [ ReceivedReceipt ] ,
70+ ) -> Vec < ReceiptResult < ( ) > > {
71+ match receipt_check {
72+ ReceiptCheck :: CheckUnique => self . check_uniqueness_batch ( received_receipts) . await ,
73+ ReceiptCheck :: CheckAllocationId => {
74+ self . check_allocation_id_batch ( received_receipts) . await
75+ }
76+ ReceiptCheck :: CheckSignature => self . check_signature_batch ( received_receipts) . await ,
77+ ReceiptCheck :: CheckTimestamp => self . check_timestamp_batch ( received_receipts) . await ,
78+ ReceiptCheck :: CheckValue => self . check_value_batch ( received_receipts) . await ,
79+ ReceiptCheck :: CheckAndReserveEscrow => {
80+ self . check_and_reserve_escrow_batch ( received_receipts) . await
81+ }
82+ }
83+ }
84+
6185 async fn check_uniqueness (
6286 & self ,
6387 signed_receipt : & EIP712SignedMessage < Receipt > ,
@@ -76,6 +100,33 @@ impl<EA: EscrowAdapter, RCA: ReceiptChecksAdapter> ReceiptAuditor<EA, RCA> {
76100 Ok ( ( ) )
77101 }
78102
103+ async fn check_uniqueness_batch (
104+ & self ,
105+ received_receipts : & mut [ ReceivedReceipt ] ,
106+ ) -> Vec < ReceiptResult < ( ) > > {
107+ let mut results = Vec :: new ( ) ;
108+
109+ // If at least one of the receipts in the batch hasn't been checked for uniqueness yet, check the whole batch.
110+ if received_receipts
111+ . iter ( )
112+ . filter ( |r| r. checks . contains_key ( & ReceiptCheck :: CheckUnique ) )
113+ . any ( |r| r. checks [ & ReceiptCheck :: CheckUnique ] . is_none ( ) )
114+ {
115+ let mut signatures: HashSet < Signature > = HashSet :: new ( ) ;
116+
117+ for received_receipt in received_receipts {
118+ let signature = received_receipt. signed_receipt . signature ;
119+ if signatures. insert ( signature) {
120+ results. push ( Ok ( ( ) ) ) ;
121+ } else {
122+ results. push ( Err ( ReceiptError :: NonUniqueReceipt ) ) ;
123+ }
124+ }
125+ }
126+
127+ results
128+ }
129+
79130 async fn check_allocation_id (
80131 & self ,
81132 signed_receipt : & EIP712SignedMessage < Receipt > ,
@@ -95,6 +146,25 @@ impl<EA: EscrowAdapter, RCA: ReceiptChecksAdapter> ReceiptAuditor<EA, RCA> {
95146 Ok ( ( ) )
96147 }
97148
149+ async fn check_allocation_id_batch (
150+ & self ,
151+ received_receipts : & mut [ ReceivedReceipt ] ,
152+ ) -> Vec < ReceiptResult < ( ) > > {
153+ let mut results = Vec :: new ( ) ;
154+
155+ for received_receipt in received_receipts
156+ . iter_mut ( )
157+ . filter ( |r| r. checks . contains_key ( & ReceiptCheck :: CheckAllocationId ) )
158+ {
159+ if received_receipt. checks [ & ReceiptCheck :: CheckAllocationId ] . is_none ( ) {
160+ let signed_receipt = & received_receipt. signed_receipt ;
161+ results. push ( self . check_allocation_id ( signed_receipt) . await ) ;
162+ }
163+ }
164+
165+ results
166+ }
167+
98168 async fn check_timestamp (
99169 & self ,
100170 signed_receipt : & EIP712SignedMessage < Receipt > ,
@@ -108,6 +178,26 @@ impl<EA: EscrowAdapter, RCA: ReceiptChecksAdapter> ReceiptAuditor<EA, RCA> {
108178 }
109179 Ok ( ( ) )
110180 }
181+
182+ async fn check_timestamp_batch (
183+ & self ,
184+ received_receipts : & mut [ ReceivedReceipt ] ,
185+ ) -> Vec < ReceiptResult < ( ) > > {
186+ let mut results = Vec :: new ( ) ;
187+
188+ for received_receipt in received_receipts
189+ . iter_mut ( )
190+ . filter ( |r| r. checks . contains_key ( & ReceiptCheck :: CheckTimestamp ) )
191+ {
192+ if received_receipt. checks [ & ReceiptCheck :: CheckTimestamp ] . is_none ( ) {
193+ let signed_receipt = & received_receipt. signed_receipt ;
194+ results. push ( self . check_timestamp ( signed_receipt) . await ) ;
195+ }
196+ }
197+
198+ results
199+ }
200+
111201 async fn check_value (
112202 & self ,
113203 signed_receipt : & EIP712SignedMessage < Receipt > ,
@@ -128,6 +218,28 @@ impl<EA: EscrowAdapter, RCA: ReceiptChecksAdapter> ReceiptAuditor<EA, RCA> {
128218 Ok ( ( ) )
129219 }
130220
221+ async fn check_value_batch (
222+ & self ,
223+ received_receipts : & mut [ ReceivedReceipt ] ,
224+ ) -> Vec < ReceiptResult < ( ) > > {
225+ let mut results = Vec :: new ( ) ;
226+
227+ for received_receipt in received_receipts
228+ . iter_mut ( )
229+ . filter ( |r| r. checks . contains_key ( & ReceiptCheck :: CheckValue ) )
230+ {
231+ if received_receipt. checks [ & ReceiptCheck :: CheckValue ] . is_none ( ) {
232+ let signed_receipt = & received_receipt. signed_receipt ;
233+ results. push (
234+ self . check_value ( signed_receipt, received_receipt. query_id )
235+ . await ,
236+ ) ;
237+ }
238+ }
239+
240+ results
241+ }
242+
131243 async fn check_signature (
132244 & self ,
133245 signed_receipt : & EIP712SignedMessage < Receipt > ,
@@ -155,6 +267,25 @@ impl<EA: EscrowAdapter, RCA: ReceiptChecksAdapter> ReceiptAuditor<EA, RCA> {
155267 Ok ( ( ) )
156268 }
157269
270+ async fn check_signature_batch (
271+ & self ,
272+ received_receipts : & mut [ ReceivedReceipt ] ,
273+ ) -> Vec < ReceiptResult < ( ) > > {
274+ let mut results = Vec :: new ( ) ;
275+
276+ for received_receipt in received_receipts
277+ . iter_mut ( )
278+ . filter ( |r| r. checks . contains_key ( & ReceiptCheck :: CheckSignature ) )
279+ {
280+ if received_receipt. checks [ & ReceiptCheck :: CheckSignature ] . is_none ( ) {
281+ let signed_receipt = & received_receipt. signed_receipt ;
282+ results. push ( self . check_signature ( signed_receipt) . await ) ;
283+ }
284+ }
285+
286+ results
287+ }
288+
158289 async fn check_and_reserve_escrow (
159290 & self ,
160291 signed_receipt : & EIP712SignedMessage < Receipt > ,
@@ -176,6 +307,22 @@ impl<EA: EscrowAdapter, RCA: ReceiptChecksAdapter> ReceiptAuditor<EA, RCA> {
176307 Ok ( ( ) )
177308 }
178309
310+ async fn check_and_reserve_escrow_batch (
311+ & self ,
312+ received_receipts : & mut [ ReceivedReceipt ] ,
313+ ) -> Vec < ReceiptResult < ( ) > > {
314+ let mut results = Vec :: new ( ) ;
315+
316+ for received_receipt in received_receipts. iter_mut ( ) . filter ( |r| {
317+ r. escrow_reserve_attempt_required ( ) && !r. escrow_reserve_attempt_completed ( )
318+ } ) {
319+ let signed_receipt = & received_receipt. signed_receipt ;
320+ results. push ( self . check_and_reserve_escrow ( signed_receipt) . await ) ;
321+ }
322+
323+ results
324+ }
325+
179326 pub async fn check_rav_signature (
180327 & self ,
181328 signed_rav : & EIP712SignedMessage < ReceiptAggregateVoucher > ,
0 commit comments