Skip to content

Commit efd88a2

Browse files
committed
fix(tap-manager): receipts being used after being added to RAV
receipts were being added to RAVs but the next RAV request would still contain the receipts causing RAV requests to fail. BREAKING CHANGE: RAV Request definition is updated to include optional previous RAV Signed-off-by: Bryan Cole <[email protected]>
1 parent 4143ac6 commit efd88a2

File tree

3 files changed

+139
-7
lines changed

3 files changed

+139
-7
lines changed

tap_core/src/tap_manager/manager.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,15 @@ impl<
129129
});
130130
}
131131

132-
self.rav_storage_adapter
132+
let rav_id = self
133+
.rav_storage_adapter
133134
.store_rav(signed_rav)
134135
.map_err(|err| Error::AdapterError {
135136
source_error_message: err.to_string(),
136137
})?;
137138

139+
self.current_rav_id = Some(rav_id);
140+
138141
Ok(())
139142
}
140143

@@ -148,16 +151,22 @@ impl<
148151
///
149152
pub fn create_rav_request(&mut self, timestamp_buffer_ns: u64) -> Result<RAVRequest, Error> {
150153
let previous_rav = self.get_previous_rav()?;
154+
let min_timestamp_ns = previous_rav
155+
.as_ref()
156+
.map(|rav| rav.message.timestamp_ns + 1)
157+
.unwrap_or(0);
151158

152-
let (valid_receipts, invalid_receipts) = self.collect_receipts(timestamp_buffer_ns)?;
159+
let (valid_receipts, invalid_receipts) =
160+
self.collect_receipts(timestamp_buffer_ns, min_timestamp_ns)?;
153161

154-
let expected_rav = Self::generate_expected_rav(&valid_receipts, previous_rav)?;
162+
let expected_rav = Self::generate_expected_rav(&valid_receipts, previous_rav.clone())?;
155163

156164
self.receipt_auditor
157165
.update_min_timestamp_ns(expected_rav.timestamp_ns + 1);
158166

159167
Ok(RAVRequest {
160168
valid_receipts,
169+
previous_rav,
161170
invalid_receipts,
162171
expected_rav,
163172
})
@@ -181,11 +190,12 @@ impl<
181190
fn collect_receipts(
182191
&mut self,
183192
timestamp_buffer_ns: u64,
193+
min_timestamp_ns: u64,
184194
) -> Result<(Vec<SignedReceipt>, Vec<SignedReceipt>), Error> {
185-
let cutoff_timestamp = crate::get_current_timestamp_u64_ns()? - timestamp_buffer_ns;
195+
let max_timestamp_ns = crate::get_current_timestamp_u64_ns()? - timestamp_buffer_ns;
186196
let received_receipts = self
187197
.receipt_storage_adapter
188-
.retrieve_receipts_upto_timestamp(cutoff_timestamp)
198+
.retrieve_receipts_in_timestamp_range(min_timestamp_ns..max_timestamp_ns)
189199
.map_err(|err| Error::AdapterError {
190200
source_error_message: err.to_string(),
191201
})?;

tap_core/src/tap_manager/rav_request.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33

44
use serde::{Deserialize, Serialize};
55

6-
use super::SignedReceipt;
6+
use super::{SignedRAV, SignedReceipt};
77
use crate::receipt_aggregate_voucher::ReceiptAggregateVoucher;
88

99
#[derive(Debug, Serialize, Deserialize, Clone)]
1010

1111
pub struct RAVRequest {
1212
pub valid_receipts: Vec<SignedReceipt>,
13+
pub previous_rav: Option<SignedRAV>,
1314
pub invalid_receipts: Vec<SignedReceipt>,
1415
pub expected_rav: ReceiptAggregateVoucher,
1516
}

tap_core/src/tap_manager/test/manager_test.rs

Lines changed: 122 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ mod manager_unit_test {
176176
get_full_list_of_checks(),
177177
starting_min_timestamp,
178178
);
179+
collateral_storage.write().unwrap().insert(keys.1, 999999);
179180

180181
let mut stored_signed_receipts = Vec::new();
181182
for query_id in 0..10 {
@@ -189,7 +190,6 @@ mod manager_unit_test {
189190
.write()
190191
.unwrap()
191192
.insert(query_id, value);
192-
collateral_storage.write().unwrap().insert(keys.1, 999999);
193193
assert!(manager
194194
.verify_and_store_receipt(signed_receipt, query_id, initial_checks.clone())
195195
.is_ok());
@@ -213,4 +213,125 @@ mod manager_unit_test {
213213
.verify_and_store_rav(rav_request.expected_rav, signed_rav)
214214
.is_ok());
215215
}
216+
217+
#[rstest]
218+
#[case::full_checks(get_full_list_of_checks())]
219+
#[case::partial_checks(vec![ReceiptCheck::CheckSignature])]
220+
#[case::no_checks(Vec::<ReceiptCheck>::new())]
221+
async fn manager_create_multiple_rav_requests_all_valid_receipts(
222+
rav_storage_adapter: RAVStorageAdapterMock,
223+
collateral_adapters: (CollateralAdapterMock, Arc<RwLock<HashMap<Address, u128>>>),
224+
receipt_adapters: (
225+
ReceiptStorageAdapterMock,
226+
ReceiptChecksAdapterMock,
227+
Arc<RwLock<HashMap<u64, u128>>>,
228+
),
229+
keys: (LocalWallet, Address),
230+
allocation_ids: Vec<Address>,
231+
#[case] initial_checks: Vec<ReceiptCheck>,
232+
) {
233+
let (collateral_adapter, collateral_storage) = collateral_adapters;
234+
let (receipt_storage_adapter, receipt_checks_adapter, query_appraisal_storage) =
235+
receipt_adapters;
236+
// give receipt 5 second variance for min start time
237+
let starting_min_timestamp = get_current_timestamp_u64_ns().unwrap() - 500000000;
238+
239+
let mut manager = Manager::new(
240+
collateral_adapter,
241+
receipt_checks_adapter,
242+
rav_storage_adapter,
243+
receipt_storage_adapter,
244+
get_full_list_of_checks(),
245+
starting_min_timestamp,
246+
);
247+
248+
collateral_storage.write().unwrap().insert(keys.1, 999999);
249+
250+
let mut stored_signed_receipts = Vec::new();
251+
let mut expected_accumulated_value = 0;
252+
for query_id in 0..10 {
253+
let value = 20u128;
254+
let signed_receipt =
255+
EIP712SignedMessage::new(Receipt::new(allocation_ids[0], value).unwrap(), &keys.0)
256+
.await
257+
.unwrap();
258+
stored_signed_receipts.push(signed_receipt.clone());
259+
query_appraisal_storage
260+
.write()
261+
.unwrap()
262+
.insert(query_id, value);
263+
assert!(manager
264+
.verify_and_store_receipt(signed_receipt, query_id, initial_checks.clone())
265+
.is_ok());
266+
expected_accumulated_value += value;
267+
}
268+
let rav_request_result = manager.create_rav_request(0);
269+
assert!(rav_request_result.is_ok());
270+
271+
let rav_request = rav_request_result.unwrap();
272+
// all receipts passing
273+
assert_eq!(
274+
rav_request.valid_receipts.len(),
275+
stored_signed_receipts.len()
276+
);
277+
// no receipts failing
278+
assert_eq!(rav_request.invalid_receipts.len(), 0);
279+
// accumulated value is correct
280+
assert_eq!(
281+
rav_request.expected_rav.value_aggregate,
282+
expected_accumulated_value
283+
);
284+
// no previous rav
285+
assert!(rav_request.previous_rav.is_none());
286+
287+
let signed_rav = EIP712SignedMessage::new(rav_request.expected_rav.clone(), &keys.0)
288+
.await
289+
.unwrap();
290+
assert!(manager
291+
.verify_and_store_rav(rav_request.expected_rav, signed_rav)
292+
.is_ok());
293+
294+
stored_signed_receipts.clear();
295+
for query_id in 10..20 {
296+
let value = 20u128;
297+
let signed_receipt =
298+
EIP712SignedMessage::new(Receipt::new(allocation_ids[0], value).unwrap(), &keys.0)
299+
.await
300+
.unwrap();
301+
stored_signed_receipts.push(signed_receipt.clone());
302+
query_appraisal_storage
303+
.write()
304+
.unwrap()
305+
.insert(query_id, value);
306+
assert!(manager
307+
.verify_and_store_receipt(signed_receipt, query_id, initial_checks.clone())
308+
.is_ok());
309+
expected_accumulated_value += value;
310+
}
311+
let rav_request_result = manager.create_rav_request(0);
312+
assert!(rav_request_result.is_ok());
313+
314+
let rav_request = rav_request_result.unwrap();
315+
// all receipts passing
316+
assert_eq!(
317+
rav_request.valid_receipts.len(),
318+
stored_signed_receipts.len()
319+
);
320+
// no receipts failing
321+
assert_eq!(rav_request.invalid_receipts.len(), 0);
322+
// accumulated value is correct
323+
assert_eq!(
324+
rav_request.expected_rav.value_aggregate,
325+
expected_accumulated_value
326+
);
327+
// no previous rav
328+
assert!(rav_request.previous_rav.is_some());
329+
330+
let signed_rav = EIP712SignedMessage::new(rav_request.expected_rav.clone(), &keys.0)
331+
.await
332+
.unwrap();
333+
assert!(manager
334+
.verify_and_store_rav(rav_request.expected_rav, signed_rav)
335+
.is_ok());
336+
}
216337
}

0 commit comments

Comments
 (0)