diff --git a/tap_core/src/adapters/mock/executor_mock.rs b/tap_core/src/adapters/mock/executor_mock.rs index 78ea36c1..f8f62ed8 100644 --- a/tap_core/src/adapters/mock/executor_mock.rs +++ b/tap_core/src/adapters/mock/executor_mock.rs @@ -18,6 +18,8 @@ use tokio::sync::RwLock; pub type EscrowStorage = Arc>>; pub type QueryAppraisals = Arc>>; +pub type ReceiptStorage = Arc>>; +pub type RAVStorage = Arc>>; use thiserror::Error; @@ -30,8 +32,8 @@ pub enum AdapterErrorMock { #[derive(Clone)] pub struct ExecutorMock { /// local RAV store with rwlocks to allow sharing with other compenents as needed - rav_storage: Arc>>, - receipt_storage: Arc>>, + rav_storage: RAVStorage, + receipt_storage: ReceiptStorage, unique_id: Arc>, sender_escrow_storage: EscrowStorage, @@ -39,9 +41,9 @@ pub struct ExecutorMock { impl ExecutorMock { pub fn new( - rav_storage: Arc>>, - receipt_storage: Arc>>, - sender_escrow_storage: Arc>>, + rav_storage: RAVStorage, + receipt_storage: ReceiptStorage, + sender_escrow_storage: EscrowStorage, ) -> Self { ExecutorMock { rav_storage, diff --git a/tap_core/src/checks/mod.rs b/tap_core/src/checks/mod.rs index 7b4e9303..9dd62864 100644 --- a/tap_core/src/checks/mod.rs +++ b/tap_core/src/checks/mod.rs @@ -139,13 +139,14 @@ pub mod tests { async fn check(&self, receipt: &ReceiptWithState) -> ReceiptResult<()> { let receipt_storage = self.receipt_storage.read().await; // let receipt_id = receipt. - receipt_storage + let unique = receipt_storage .iter() .all(|(_stored_receipt_id, stored_receipt)| { stored_receipt.signed_receipt().message != receipt.signed_receipt().message - }) - .then_some(()) - .ok_or(ReceiptError::NonUniqueReceipt) + || stored_receipt.query_id() == receipt.query_id + }); + + unique.then_some(()).ok_or(ReceiptError::NonUniqueReceipt) } async fn check_batch( diff --git a/tap_core/src/tap_manager/test/manager_test.rs b/tap_core/src/tap_manager/test/manager_test.rs index c25a2390..b957193b 100644 --- a/tap_core/src/tap_manager/test/manager_test.rs +++ b/tap_core/src/tap_manager/test/manager_test.rs @@ -1,112 +1,197 @@ // Copyright 2023-, Semiotic AI, Inc. // SPDX-License-Identifier: Apache-2.0 -#[cfg(test)] -#[allow(clippy::too_many_arguments)] -mod manager_unit_test { - use std::{collections::HashMap, str::FromStr, sync::Arc}; - - use alloy_primitives::Address; - use alloy_sol_types::Eip712Domain; - use ethers::signers::{coins_bip39::English, LocalWallet, MnemonicBuilder, Signer}; - use rstest::*; - use tokio::sync::RwLock; - - use super::super::Manager; - use crate::{ - adapters::{ - executor_mock::{EscrowStorage, ExecutorMock, QueryAppraisals}, - receipt_storage_adapter::ReceiptRead, - }, - checks::ReceiptCheck, - eip_712_signed_message::EIP712SignedMessage, - get_current_timestamp_u64_ns, tap_eip712_domain, - tap_receipt::Receipt, - }; - - #[fixture] - fn keys() -> (LocalWallet, Address) { - let wallet: LocalWallet = MnemonicBuilder::::default() - .phrase("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about") - .build() - .unwrap(); - // Alloy library does not have feature parity with ethers library (yet) This workaround is needed to get the address - // to convert to an alloy Address. This will not be needed when the alloy library has wallet support. - let address: [u8; 20] = wallet.address().into(); - - (wallet, address.into()) - } +use std::{collections::HashMap, ops::Range, str::FromStr, sync::Arc}; + +use alloy_primitives::Address; +use alloy_sol_types::Eip712Domain; +use ethers::signers::{coins_bip39::English, LocalWallet, MnemonicBuilder, Signer}; +use rstest::*; +use tokio::sync::RwLock; + +use super::super::Manager; +use crate::{ + adapters::{ + executor_mock::{EscrowStorage, ExecutorMock, QueryAppraisals, RAVStorage, ReceiptStorage}, + receipt_storage_adapter::ReceiptRead, + }, + checks::{tests::get_full_list_of_checks, ReceiptCheck}, + eip_712_signed_message::EIP712SignedMessage, + get_current_timestamp_u64_ns, tap_eip712_domain, + tap_receipt::Receipt, +}; + +#[fixture] +fn keys() -> (LocalWallet, Address) { + let wallet: LocalWallet = MnemonicBuilder::::default() + .phrase("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about") + .build() + .unwrap(); + // Alloy library does not have feature parity with ethers library (yet) This workaround is needed to get the address + // to convert to an alloy Address. This will not be needed when the alloy library has wallet support. + let address: [u8; 20] = wallet.address().into(); - #[fixture] - fn allocation_ids() -> Vec
{ - vec![ - Address::from_str("0xabababababababababababababababababababab").unwrap(), - Address::from_str("0xdeaddeaddeaddeaddeaddeaddeaddeaddeaddead").unwrap(), - Address::from_str("0xbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef").unwrap(), - Address::from_str("0x1234567890abcdef1234567890abcdef12345678").unwrap(), - ] - } + (wallet, address.into()) +} - #[fixture] - fn sender_ids() -> Vec
{ - vec![ - Address::from_str("0xfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfb").unwrap(), - Address::from_str("0xfafafafafafafafafafafafafafafafafafafafa").unwrap(), - Address::from_str("0xadadadadadadadadadadadadadadadadadadadad").unwrap(), - keys().1, - ] - } +#[fixture] +fn allocation_ids() -> Vec
{ + vec![ + Address::from_str("0xabababababababababababababababababababab").unwrap(), + Address::from_str("0xdeaddeaddeaddeaddeaddeaddeaddeaddeaddead").unwrap(), + Address::from_str("0xbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef").unwrap(), + Address::from_str("0x1234567890abcdef1234567890abcdef12345678").unwrap(), + ] +} - #[fixture] - fn full_list_of_checks() -> Vec { - vec![] - } +#[fixture] +fn sender_ids() -> Vec
{ + vec![ + Address::from_str("0xfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfb").unwrap(), + Address::from_str("0xfafafafafafafafafafafafafafafafafafafafa").unwrap(), + Address::from_str("0xadadadadadadadadadadadadadadadadadadadad").unwrap(), + keys().1, + ] +} - #[fixture] - fn domain_separator() -> Eip712Domain { - tap_eip712_domain(1, Address::from([0x11u8; 20])) - } +#[fixture] +fn receipt_storage() -> ReceiptStorage { + Arc::new(RwLock::new(HashMap::new())) +} - #[fixture] - fn executor_mock() -> (ExecutorMock, EscrowStorage, QueryAppraisals) { - let rav_storage = Arc::new(RwLock::new(None)); - let receipt_storage = Arc::new(RwLock::new(HashMap::new())); +#[fixture] +fn query_appraisal_storage() -> QueryAppraisals { + Arc::new(RwLock::new(HashMap::new())) +} - let sender_escrow_storage = Arc::new(RwLock::new(HashMap::new())); +#[fixture] +fn rav_storage() -> RAVStorage { + Arc::new(RwLock::new(None)) +} - let query_appraisal_storage = Arc::new(RwLock::new(HashMap::new())); +#[fixture] +fn escrow_storage() -> EscrowStorage { + Arc::new(RwLock::new(HashMap::new())) +} - ( - ExecutorMock::new(rav_storage, receipt_storage, sender_escrow_storage.clone()), - sender_escrow_storage, - query_appraisal_storage, - ) +#[fixture] +fn domain_separator() -> Eip712Domain { + tap_eip712_domain(1, Address::from([0x11u8; 20])) +} + +struct ExecutorFixture { + executor: ExecutorMock, + escrow_storage: EscrowStorage, + query_appraisals: QueryAppraisals, + checks: Vec, +} + +#[fixture] +fn executor_mock( + domain_separator: Eip712Domain, + allocation_ids: Vec
, + sender_ids: Vec
, + receipt_storage: ReceiptStorage, + query_appraisal_storage: QueryAppraisals, + rav_storage: RAVStorage, + escrow_storage: EscrowStorage, +) -> ExecutorFixture { + let executor = ExecutorMock::new(rav_storage, receipt_storage.clone(), escrow_storage.clone()); + + let checks = get_full_list_of_checks( + domain_separator, + sender_ids.iter().cloned().collect(), + Arc::new(RwLock::new(allocation_ids.iter().cloned().collect())), + receipt_storage, + query_appraisal_storage.clone(), + ); + + ExecutorFixture { + executor, + escrow_storage, + query_appraisals: query_appraisal_storage, + checks, } +} - #[rstest] - // #[case::full_checks(get_full_list_of_checks())] - // #[case::partial_checks(todo!())] - #[case::no_checks(Vec::::new())] - #[tokio::test] - async fn manager_verify_and_store_varying_initial_checks( - executor_mock: (ExecutorMock, EscrowStorage, QueryAppraisals), - keys: (LocalWallet, Address), - allocation_ids: Vec
, - domain_separator: Eip712Domain, - #[case] initial_checks: Vec, - full_list_of_checks: Vec, - ) { - let (executor, escrow_storage, query_appraisal_storage) = executor_mock; - // give receipt 5 second variance for min start time - let starting_min_timestamp = get_current_timestamp_u64_ns().unwrap() - 500000000; - - let manager = Manager::new( - domain_separator.clone(), - executor, - full_list_of_checks, - starting_min_timestamp, - ); +#[rstest] +#[case::full_checks(0..5)] +#[case::partial_checks(0..2)] +#[case::no_checks(0..0)] +#[tokio::test] +async fn manager_verify_and_store_varying_initial_checks( + keys: (LocalWallet, Address), + allocation_ids: Vec
, + domain_separator: Eip712Domain, + #[case] range: Range, + executor_mock: ExecutorFixture, +) { + let ExecutorFixture { + executor, + checks, + query_appraisals, + escrow_storage, + .. + } = executor_mock; + // give receipt 5 second variance for min start time + let starting_min_timestamp = get_current_timestamp_u64_ns().unwrap() - 500000000; + + let manager = Manager::new( + domain_separator.clone(), + executor, + checks.clone(), + starting_min_timestamp, + ); + + let query_id = 1; + let value = 20u128; + let signed_receipt = EIP712SignedMessage::new( + &domain_separator, + Receipt::new(allocation_ids[0], value).unwrap(), + &keys.0, + ) + .unwrap(); + query_appraisals.write().await.insert(query_id, value); + escrow_storage.write().await.insert(keys.1, 999999); + + assert!(manager + .verify_and_store_receipt(signed_receipt, query_id, &checks[range]) + .await + .is_ok()); +} - let query_id = 1; +#[rstest] +#[case::full_checks(0..5)] +#[case::partial_checks(0..2)] +#[case::no_checks(0..0)] +#[tokio::test] +async fn manager_create_rav_request_all_valid_receipts( + keys: (LocalWallet, Address), + allocation_ids: Vec
, + domain_separator: Eip712Domain, + #[case] range: Range, + executor_mock: ExecutorFixture, +) { + let ExecutorFixture { + executor, + checks, + query_appraisals, + escrow_storage, + .. + } = executor_mock; + let initial_checks = &checks[range]; + // give receipt 5 second variance for min start time + let starting_min_timestamp = get_current_timestamp_u64_ns().unwrap() - 500000000; + + let manager = Manager::new( + domain_separator.clone(), + executor, + checks.clone(), + starting_min_timestamp, + ); + escrow_storage.write().await.insert(keys.1, 999999); + + let mut stored_signed_receipts = Vec::new(); + for query_id in 0..10 { let value = 20u128; let signed_receipt = EIP712SignedMessage::new( &domain_separator, @@ -114,368 +199,316 @@ mod manager_unit_test { &keys.0, ) .unwrap(); - query_appraisal_storage - .write() - .await - .insert(query_id, value); - escrow_storage.write().await.insert(keys.1, 999999); - + stored_signed_receipts.push(signed_receipt.clone()); + query_appraisals.write().await.insert(query_id, value); assert!(manager - .verify_and_store_receipt(signed_receipt, query_id, initial_checks.as_slice()) + .verify_and_store_receipt(signed_receipt, query_id, initial_checks) .await .is_ok()); } - - #[rstest] - // #[case::full_checks(get_full_list_of_checks())] - // #[case::partial_checks(vec![ReceiptCheck::CheckSignature])] - #[case::no_checks(Vec::::new())] - #[tokio::test] - async fn manager_create_rav_request_all_valid_receipts( - executor_mock: (ExecutorMock, EscrowStorage, QueryAppraisals), - keys: (LocalWallet, Address), - allocation_ids: Vec
, - domain_separator: Eip712Domain, - #[case] initial_checks: Vec, - full_list_of_checks: Vec, - ) { - let (executor, escrow_storage, query_appraisal_storage) = executor_mock; - // give receipt 5 second variance for min start time - let starting_min_timestamp = get_current_timestamp_u64_ns().unwrap() - 500000000; - - let manager = Manager::new( - domain_separator.clone(), - executor, - full_list_of_checks, - starting_min_timestamp, - ); - escrow_storage.write().await.insert(keys.1, 999999); - - let mut stored_signed_receipts = Vec::new(); - for query_id in 0..10 { - let value = 20u128; - let signed_receipt = EIP712SignedMessage::new( - &domain_separator, - Receipt::new(allocation_ids[0], value).unwrap(), - &keys.0, - ) + let rav_request_result = manager.create_rav_request(0, None).await; + println!("{:?}", rav_request_result); + assert!(rav_request_result.is_ok()); + + let rav_request = rav_request_result.unwrap(); + // all passing + assert_eq!( + rav_request.valid_receipts.len(), + stored_signed_receipts.len() + ); + // no failing + assert_eq!(rav_request.invalid_receipts.len(), 0); + + let signed_rav = + EIP712SignedMessage::new(&domain_separator, rav_request.expected_rav.clone(), &keys.0) .unwrap(); - stored_signed_receipts.push(signed_receipt.clone()); - query_appraisal_storage - .write() - .await - .insert(query_id, value); - assert!(manager - .verify_and_store_receipt(signed_receipt, query_id, initial_checks.as_slice()) - .await - .is_ok()); - } - let rav_request_result = manager.create_rav_request(0, None).await; - assert!(rav_request_result.is_ok()); - - let rav_request = rav_request_result.unwrap(); - // all passing - assert_eq!( - rav_request.valid_receipts.len(), - stored_signed_receipts.len() - ); - // no failing - assert_eq!(rav_request.invalid_receipts.len(), 0); + assert!(manager + .verify_and_store_rav( + rav_request.expected_rav, + signed_rav, + |address: Address| async move { Ok(keys.1 == address) } + ) + .await + .is_ok()); +} - let signed_rav = - EIP712SignedMessage::new(&domain_separator, rav_request.expected_rav.clone(), &keys.0) - .unwrap(); +#[rstest] +#[case::full_checks(0..5)] +#[case::partial_checks(0..2)] +#[case::no_checks(0..0)] +#[tokio::test] +async fn manager_create_multiple_rav_requests_all_valid_receipts( + keys: (LocalWallet, Address), + allocation_ids: Vec
, + domain_separator: Eip712Domain, + #[case] range: Range, + executor_mock: ExecutorFixture, +) { + let ExecutorFixture { + executor, + checks, + query_appraisals, + escrow_storage, + .. + } = executor_mock; + let initial_checks = &checks[range]; + // give receipt 5 second variance for min start time + let starting_min_timestamp = get_current_timestamp_u64_ns().unwrap() - 500000000; + + let manager = Manager::new( + domain_separator.clone(), + executor, + checks.clone(), + starting_min_timestamp, + ); + + escrow_storage.write().await.insert(keys.1, 999999); + + let mut stored_signed_receipts = Vec::new(); + let mut expected_accumulated_value = 0; + for query_id in 0..10 { + let value = 20u128; + let signed_receipt = EIP712SignedMessage::new( + &domain_separator, + Receipt::new(allocation_ids[0], value).unwrap(), + &keys.0, + ) + .unwrap(); + stored_signed_receipts.push(signed_receipt.clone()); + query_appraisals.write().await.insert(query_id, value); assert!(manager - .verify_and_store_rav( - rav_request.expected_rav, - signed_rav, - |address: Address| async move { Ok(keys.1 == address) } - ) + .verify_and_store_receipt(signed_receipt, query_id, initial_checks) .await .is_ok()); + expected_accumulated_value += value; } - - #[rstest] - // #[case::full_checks(get_full_list_of_checks())] - // #[case::partial_checks(vec![ReceiptCheck::CheckSignature])] - #[case::no_checks(Vec::::new())] - #[tokio::test] - async fn manager_create_multiple_rav_requests_all_valid_receipts( - executor_mock: (ExecutorMock, EscrowStorage, QueryAppraisals), - keys: (LocalWallet, Address), - allocation_ids: Vec
, - domain_separator: Eip712Domain, - #[case] initial_checks: Vec, - full_list_of_checks: Vec, - ) { - let (executor, escrow_storage, query_appraisal_storage) = executor_mock; - // give receipt 5 second variance for min start time - let starting_min_timestamp = get_current_timestamp_u64_ns().unwrap() - 500000000; - - let manager = Manager::new( - domain_separator.clone(), - executor, - full_list_of_checks, - starting_min_timestamp, - ); - - escrow_storage.write().await.insert(keys.1, 999999); - - let mut stored_signed_receipts = Vec::new(); - let mut expected_accumulated_value = 0; - for query_id in 0..10 { - let value = 20u128; - let signed_receipt = EIP712SignedMessage::new( - &domain_separator, - Receipt::new(allocation_ids[0], value).unwrap(), - &keys.0, - ) + let rav_request_result = manager.create_rav_request(0, None).await; + assert!(rav_request_result.is_ok()); + + let rav_request = rav_request_result.unwrap(); + // all receipts passing + assert_eq!( + rav_request.valid_receipts.len(), + stored_signed_receipts.len() + ); + // no receipts failing + assert_eq!(rav_request.invalid_receipts.len(), 0); + // accumulated value is correct + assert_eq!( + rav_request.expected_rav.valueAggregate, + expected_accumulated_value + ); + // no previous rav + assert!(rav_request.previous_rav.is_none()); + + let signed_rav = + EIP712SignedMessage::new(&domain_separator, rav_request.expected_rav.clone(), &keys.0) .unwrap(); - stored_signed_receipts.push(signed_receipt.clone()); - query_appraisal_storage - .write() - .await - .insert(query_id, value); - assert!(manager - .verify_and_store_receipt(signed_receipt, query_id, initial_checks.as_slice()) - .await - .is_ok()); - expected_accumulated_value += value; - } - let rav_request_result = manager.create_rav_request(0, None).await; - assert!(rav_request_result.is_ok()); - - let rav_request = rav_request_result.unwrap(); - // all receipts passing - assert_eq!( - rav_request.valid_receipts.len(), - stored_signed_receipts.len() - ); - // no receipts failing - assert_eq!(rav_request.invalid_receipts.len(), 0); - // accumulated value is correct - assert_eq!( - rav_request.expected_rav.valueAggregate, - expected_accumulated_value - ); - // no previous rav - assert!(rav_request.previous_rav.is_none()); + assert!(manager + .verify_and_store_rav( + rav_request.expected_rav, + signed_rav, + |address: Address| async move { Ok(keys.1 == address) } + ) + .await + .is_ok()); - let signed_rav = - EIP712SignedMessage::new(&domain_separator, rav_request.expected_rav.clone(), &keys.0) - .unwrap(); + stored_signed_receipts.clear(); + for query_id in 10..20 { + let value = 20u128; + let signed_receipt = EIP712SignedMessage::new( + &domain_separator, + Receipt::new(allocation_ids[0], value).unwrap(), + &keys.0, + ) + .unwrap(); + stored_signed_receipts.push(signed_receipt.clone()); + query_appraisals.write().await.insert(query_id, value); assert!(manager - .verify_and_store_rav( - rav_request.expected_rav, - signed_rav, - |address: Address| async move { Ok(keys.1 == address) } - ) + .verify_and_store_receipt(signed_receipt, query_id, initial_checks) .await .is_ok()); - - stored_signed_receipts.clear(); - for query_id in 10..20 { - let value = 20u128; - let signed_receipt = EIP712SignedMessage::new( - &domain_separator, - Receipt::new(allocation_ids[0], value).unwrap(), - &keys.0, - ) + expected_accumulated_value += value; + } + let rav_request_result = manager.create_rav_request(0, None).await; + assert!(rav_request_result.is_ok()); + + let rav_request = rav_request_result.unwrap(); + // all receipts passing + assert_eq!( + rav_request.valid_receipts.len(), + stored_signed_receipts.len() + ); + // no receipts failing + assert_eq!(rav_request.invalid_receipts.len(), 0); + // accumulated value is correct + assert_eq!( + rav_request.expected_rav.valueAggregate, + expected_accumulated_value + ); + // Verify there is a previous rav + assert!(rav_request.previous_rav.is_some()); + + let signed_rav = + EIP712SignedMessage::new(&domain_separator, rav_request.expected_rav.clone(), &keys.0) .unwrap(); - stored_signed_receipts.push(signed_receipt.clone()); - query_appraisal_storage - .write() - .await - .insert(query_id, value); - assert!(manager - .verify_and_store_receipt(signed_receipt, query_id, initial_checks.as_slice()) - .await - .is_ok()); - expected_accumulated_value += value; - } - let rav_request_result = manager.create_rav_request(0, None).await; - assert!(rav_request_result.is_ok()); - - let rav_request = rav_request_result.unwrap(); - // all receipts passing - assert_eq!( - rav_request.valid_receipts.len(), - stored_signed_receipts.len() - ); - // no receipts failing - assert_eq!(rav_request.invalid_receipts.len(), 0); - // accumulated value is correct - assert_eq!( - rav_request.expected_rav.valueAggregate, - expected_accumulated_value - ); - // Verify there is a previous rav - assert!(rav_request.previous_rav.is_some()); + assert!(manager + .verify_and_store_rav( + rav_request.expected_rav, + signed_rav, + |address: Address| async move { Ok(keys.1 == address) } + ) + .await + .is_ok()); +} - let signed_rav = - EIP712SignedMessage::new(&domain_separator, rav_request.expected_rav.clone(), &keys.0) - .unwrap(); +#[rstest] +#[tokio::test] +async fn manager_create_multiple_rav_requests_all_valid_receipts_consecutive_timestamps( + keys: (LocalWallet, Address), + allocation_ids: Vec
, + domain_separator: Eip712Domain, + #[values(0..0, 0..2, 0..5)] range: Range, + #[values(true, false)] remove_old_receipts: bool, + executor_mock: ExecutorFixture, +) { + let ExecutorFixture { + executor, + checks, + query_appraisals, + escrow_storage, + .. + } = executor_mock; + let initial_checks = &checks[range]; + // give receipt 5 second variance for min start time + let starting_min_timestamp = get_current_timestamp_u64_ns().unwrap() - 500000000; + + let manager = Manager::new( + domain_separator.clone(), + executor, + checks.clone(), + starting_min_timestamp, + ); + + escrow_storage.write().await.insert(keys.1, 999999); + + let mut stored_signed_receipts = Vec::new(); + let mut expected_accumulated_value = 0; + for query_id in 0..10 { + let value = 20u128; + let mut receipt = Receipt::new(allocation_ids[0], value).unwrap(); + receipt.timestamp_ns = starting_min_timestamp + query_id + 1; + let signed_receipt = EIP712SignedMessage::new(&domain_separator, receipt, &keys.0).unwrap(); + stored_signed_receipts.push(signed_receipt.clone()); + query_appraisals.write().await.insert(query_id, value); assert!(manager - .verify_and_store_rav( - rav_request.expected_rav, - signed_rav, - |address: Address| async move { Ok(keys.1 == address) } - ) + .verify_and_store_receipt(signed_receipt, query_id, initial_checks) .await .is_ok()); + expected_accumulated_value += value; } - #[rstest] - #[tokio::test] - async fn manager_create_multiple_rav_requests_all_valid_receipts_consecutive_timestamps( - executor_mock: (ExecutorMock, EscrowStorage, QueryAppraisals), - keys: (LocalWallet, Address), - allocation_ids: Vec
, - domain_separator: Eip712Domain, - #[values(/*get_full_list_of_checks(), vec![ReceiptCheck::CheckSignature], */Vec::::new())] - initial_checks: Vec, - #[values(true, false)] remove_old_receipts: bool, - full_list_of_checks: Vec, - ) { - let (executor, escrow_storage, query_appraisal_storage) = executor_mock; - // give receipt 5 second variance for min start time - let starting_min_timestamp = get_current_timestamp_u64_ns().unwrap() - 500000000; - - let manager = Manager::new( - domain_separator.clone(), - executor, - full_list_of_checks, - starting_min_timestamp, - ); - - escrow_storage.write().await.insert(keys.1, 999999); - - let mut stored_signed_receipts = Vec::new(); - let mut expected_accumulated_value = 0; - for query_id in 0..10 { - let value = 20u128; - let mut receipt = Receipt::new(allocation_ids[0], value).unwrap(); - receipt.timestamp_ns = starting_min_timestamp + query_id + 1; - let signed_receipt = - EIP712SignedMessage::new(&domain_separator, receipt, &keys.0).unwrap(); - stored_signed_receipts.push(signed_receipt.clone()); - query_appraisal_storage - .write() - .await - .insert(query_id, value); - assert!(manager - .verify_and_store_receipt(signed_receipt, query_id, initial_checks.as_slice()) - .await - .is_ok()); - expected_accumulated_value += value; - } - - // Remove old receipts if requested - // This shouldn't do anything since there has been no rav created yet - if remove_old_receipts { - manager.remove_obsolete_receipts().await.unwrap(); - } - - let rav_request_1_result = manager.create_rav_request(0, None).await; - assert!(rav_request_1_result.is_ok()); - - let rav_request_1 = rav_request_1_result.unwrap(); - // all receipts passing - assert_eq!( - rav_request_1.valid_receipts.len(), - stored_signed_receipts.len() - ); - // no receipts failing - assert_eq!(rav_request_1.invalid_receipts.len(), 0); - // accumulated value is correct - assert_eq!( - rav_request_1.expected_rav.valueAggregate, - expected_accumulated_value - ); - // no previous rav - assert!(rav_request_1.previous_rav.is_none()); + // Remove old receipts if requested + // This shouldn't do anything since there has been no rav created yet + if remove_old_receipts { + manager.remove_obsolete_receipts().await.unwrap(); + } - let signed_rav_1 = EIP712SignedMessage::new( - &domain_separator, - rav_request_1.expected_rav.clone(), - &keys.0, + let rav_request_1_result = manager.create_rav_request(0, None).await; + assert!(rav_request_1_result.is_ok()); + + let rav_request_1 = rav_request_1_result.unwrap(); + // all receipts passing + assert_eq!( + rav_request_1.valid_receipts.len(), + stored_signed_receipts.len() + ); + // no receipts failing + assert_eq!(rav_request_1.invalid_receipts.len(), 0); + // accumulated value is correct + assert_eq!( + rav_request_1.expected_rav.valueAggregate, + expected_accumulated_value + ); + // no previous rav + assert!(rav_request_1.previous_rav.is_none()); + + let signed_rav_1 = EIP712SignedMessage::new( + &domain_separator, + rav_request_1.expected_rav.clone(), + &keys.0, + ) + .unwrap(); + assert!(manager + .verify_and_store_rav( + rav_request_1.expected_rav, + signed_rav_1, + |address: Address| async move { Ok(keys.1 == address) } ) - .unwrap(); + .await + .is_ok()); + + stored_signed_receipts.clear(); + for query_id in 10..20 { + let value = 20u128; + let mut receipt = Receipt::new(allocation_ids[0], value).unwrap(); + receipt.timestamp_ns = starting_min_timestamp + query_id + 1; + let signed_receipt = EIP712SignedMessage::new(&domain_separator, receipt, &keys.0).unwrap(); + stored_signed_receipts.push(signed_receipt.clone()); + query_appraisals.write().await.insert(query_id, value); assert!(manager - .verify_and_store_rav( - rav_request_1.expected_rav, - signed_rav_1, - |address: Address| async move { Ok(keys.1 == address) } - ) + .verify_and_store_receipt(signed_receipt, query_id, initial_checks) .await .is_ok()); + expected_accumulated_value += value; + } - stored_signed_receipts.clear(); - for query_id in 10..20 { - let value = 20u128; - let mut receipt = Receipt::new(allocation_ids[0], value).unwrap(); - receipt.timestamp_ns = starting_min_timestamp + query_id + 1; - let signed_receipt = - EIP712SignedMessage::new(&domain_separator, receipt, &keys.0).unwrap(); - stored_signed_receipts.push(signed_receipt.clone()); - query_appraisal_storage - .write() - .await - .insert(query_id, value); - assert!(manager - .verify_and_store_receipt(signed_receipt, query_id, initial_checks.as_slice()) - .await - .is_ok()); - expected_accumulated_value += value; - } - - // Remove old receipts if requested - if remove_old_receipts { - manager.remove_obsolete_receipts().await.unwrap(); - // We expect to have 10 receipts left in receipt storage - assert_eq!( - manager - .executor - .retrieve_receipts_in_timestamp_range(.., None) - .await - .unwrap() - .len(), - 10 - ); - } - - let rav_request_2_result = manager.create_rav_request(0, None).await; - assert!(rav_request_2_result.is_ok()); - - let rav_request_2 = rav_request_2_result.unwrap(); - // all receipts passing - assert_eq!( - rav_request_2.valid_receipts.len(), - stored_signed_receipts.len() - ); - // no receipts failing - assert_eq!(rav_request_2.invalid_receipts.len(), 0); - // accumulated value is correct + // Remove old receipts if requested + if remove_old_receipts { + manager.remove_obsolete_receipts().await.unwrap(); + // We expect to have 10 receipts left in receipt storage assert_eq!( - rav_request_2.expected_rav.valueAggregate, - expected_accumulated_value + manager + .executor + .retrieve_receipts_in_timestamp_range(.., None) + .await + .unwrap() + .len(), + 10 ); - // Verify there is a previous rav - assert!(rav_request_2.previous_rav.is_some()); + } - let signed_rav_2 = EIP712SignedMessage::new( - &domain_separator, - rav_request_2.expected_rav.clone(), - &keys.0, + let rav_request_2_result = manager.create_rav_request(0, None).await; + assert!(rav_request_2_result.is_ok()); + + let rav_request_2 = rav_request_2_result.unwrap(); + // all receipts passing + assert_eq!( + rav_request_2.valid_receipts.len(), + stored_signed_receipts.len() + ); + // no receipts failing + assert_eq!(rav_request_2.invalid_receipts.len(), 0); + // accumulated value is correct + assert_eq!( + rav_request_2.expected_rav.valueAggregate, + expected_accumulated_value + ); + // Verify there is a previous rav + assert!(rav_request_2.previous_rav.is_some()); + + let signed_rav_2 = EIP712SignedMessage::new( + &domain_separator, + rav_request_2.expected_rav.clone(), + &keys.0, + ) + .unwrap(); + assert!(manager + .verify_and_store_rav( + rav_request_2.expected_rav, + signed_rav_2, + |address: Address| async move { Ok(keys.1 == address) } ) - .unwrap(); - assert!(manager - .verify_and_store_rav( - rav_request_2.expected_rav, - signed_rav_2, - |address: Address| async move { Ok(keys.1 == address) } - ) - .await - .is_ok()); - } + .await + .is_ok()); } diff --git a/tap_core/src/tap_receipt/received_receipt/received_receipt_unit_test.rs b/tap_core/src/tap_receipt/received_receipt/received_receipt_unit_test.rs index 857e0843..5e4f3118 100644 --- a/tap_core/src/tap_receipt/received_receipt/received_receipt_unit_test.rs +++ b/tap_core/src/tap_receipt/received_receipt/received_receipt_unit_test.rs @@ -10,7 +10,9 @@ use rstest::*; use tokio::sync::RwLock; use crate::{ - adapters::executor_mock::{EscrowStorage, ExecutorMock, QueryAppraisals}, + adapters::executor_mock::{ + EscrowStorage, ExecutorMock, QueryAppraisals, RAVStorage, ReceiptStorage, + }, checks::{tests::get_full_list_of_checks, ReceiptCheck}, eip_712_signed_message::EIP712SignedMessage, get_current_timestamp_u64_ns, tap_eip712_domain, @@ -79,22 +81,23 @@ fn sender_ids() -> Vec
{ } #[fixture] -fn receipt_storage() -> Arc>> { +fn receipt_storage() -> ReceiptStorage { Arc::new(RwLock::new(HashMap::new())) } #[fixture] -fn executor_mock() -> (ExecutorMock, EscrowStorage, QueryAppraisals) { - let rav_storage = Arc::new(RwLock::new(None)); - let receipt_storage = Arc::new(RwLock::new(HashMap::new())); - let sender_escrow_storage = Arc::new(RwLock::new(HashMap::new())); - - let executor = ExecutorMock::new(rav_storage, receipt_storage, sender_escrow_storage.clone()); +fn query_appraisal_storage() -> QueryAppraisals { + Arc::new(RwLock::new(HashMap::new())) +} - let sender_escrow_storage = Arc::new(RwLock::new(HashMap::new())); +#[fixture] +fn rav_storage() -> RAVStorage { + Arc::new(RwLock::new(None)) +} - let query_appraisal_storage = Arc::new(RwLock::new(HashMap::new())); - (executor, sender_escrow_storage, query_appraisal_storage) +#[fixture] +fn escrow_storage() -> EscrowStorage { + Arc::new(RwLock::new(HashMap::new())) } #[fixture] @@ -102,22 +105,39 @@ fn domain_separator() -> Eip712Domain { tap_eip712_domain(1, Address::from([0x11u8; 20])) } +struct ExecutorFixture { + executor: ExecutorMock, + escrow_storage: EscrowStorage, + query_appraisals: QueryAppraisals, + checks: Vec, +} + #[fixture] -fn checks( +fn executor_mock( domain_separator: Eip712Domain, - executor_mock: (ExecutorMock, EscrowStorage, QueryAppraisals), - receipt_storage: Arc>>, allocation_ids: Vec
, sender_ids: Vec
, -) -> Vec { - let (_, _, query_appraisal_storage) = executor_mock; - get_full_list_of_checks( + receipt_storage: ReceiptStorage, + query_appraisal_storage: QueryAppraisals, + rav_storage: RAVStorage, + escrow_storage: EscrowStorage, +) -> ExecutorFixture { + let executor = ExecutorMock::new(rav_storage, receipt_storage.clone(), escrow_storage.clone()); + + let checks = get_full_list_of_checks( domain_separator, sender_ids.iter().cloned().collect(), Arc::new(RwLock::new(allocation_ids.iter().cloned().collect())), receipt_storage, - query_appraisal_storage, - ) + query_appraisal_storage.clone(), + ); + + ExecutorFixture { + executor, + escrow_storage, + query_appraisals: query_appraisal_storage, + checks, + } } #[rstest] @@ -126,8 +146,10 @@ async fn initialization_valid_receipt( keys: (LocalWallet, Address), allocation_ids: Vec
, domain_separator: Eip712Domain, - checks: Vec, + executor_mock: ExecutorFixture, ) { + let ExecutorFixture { checks, .. } = executor_mock; + let signed_receipt = EIP712SignedMessage::new( &domain_separator, Receipt::new(allocation_ids[0], 10).unwrap(), @@ -153,13 +175,18 @@ async fn partial_then_full_check_valid_receipt( keys: (LocalWallet, Address), domain_separator: Eip712Domain, allocation_ids: Vec
, - executor_mock: (ExecutorMock, EscrowStorage, QueryAppraisals), - checks: Vec, + executor_mock: ExecutorFixture, ) { - let (executor, escrow_storage, query_appraisal_storage) = executor_mock; + let ExecutorFixture { + checks, + executor, + escrow_storage, + query_appraisals, + .. + } = executor_mock; // give receipt 5 second variance for min start time - let _starting_min_timestamp = get_current_timestamp_u64_ns().unwrap() - 500000000; - let _receipt_auditor = ReceiptAuditor::new(domain_separator.clone(), executor); + let starting_min_timestamp = get_current_timestamp_u64_ns().unwrap() - 500000000; + let receipt_auditor = ReceiptAuditor::new(domain_separator.clone(), executor); let query_value = 20u128; let signed_receipt = EIP712SignedMessage::new( @@ -179,13 +206,10 @@ async fn partial_then_full_check_valid_receipt( .await .insert(keys.1, query_value + 500); // appraise query - query_appraisal_storage - .write() - .await - .insert(query_id, query_value); + query_appraisals.write().await.insert(query_id, query_value); let received_receipt = ReceivedReceipt::new(signed_receipt, query_id, &checks); - let _receipt_id = 0u64; + let receipt_id = 0u64; let mut received_receipt = match received_receipt { ReceivedReceipt::Checking(checking) => checking, @@ -212,12 +236,17 @@ async fn partial_then_finalize_valid_receipt( keys: (LocalWallet, Address), allocation_ids: Vec
, domain_separator: Eip712Domain, - executor_mock: (ExecutorMock, EscrowStorage, QueryAppraisals), - checks: Vec, + executor_mock: ExecutorFixture, ) { - let (executor, escrow_storage, query_appraisal_storage) = executor_mock; + let ExecutorFixture { + checks, + executor, + escrow_storage, + query_appraisals, + .. + } = executor_mock; // give receipt 5 second variance for min start time - let _starting_min_timestamp = get_current_timestamp_u64_ns().unwrap() - 500000000; + let starting_min_timestamp = get_current_timestamp_u64_ns().unwrap() - 500000000; let receipt_auditor = ReceiptAuditor::new(domain_separator.clone(), executor); let query_value = 20u128; @@ -238,13 +267,10 @@ async fn partial_then_finalize_valid_receipt( .await .insert(keys.1, query_value + 500); // appraise query - query_appraisal_storage - .write() - .await - .insert(query_id, query_value); + query_appraisals.write().await.insert(query_id, query_value); let received_receipt = ReceivedReceipt::new(signed_receipt, query_id, &checks); - let _receipt_id = 0u64; + let receipt_id = 0u64; let mut received_receipt = match received_receipt { ReceivedReceipt::Checking(checking) => checking, @@ -260,7 +286,6 @@ async fn partial_then_finalize_valid_receipt( assert!(received_receipt.check_is_complete(arbitrary_check_to_perform)); let awaiting_escrow_receipt = received_receipt.finalize_receipt_checks().await; - println!("{:?}", awaiting_escrow_receipt); assert!(awaiting_escrow_receipt.is_ok()); let awaiting_escrow_receipt = awaiting_escrow_receipt.unwrap(); @@ -276,13 +301,18 @@ async fn standard_lifetime_valid_receipt( keys: (LocalWallet, Address), allocation_ids: Vec
, domain_separator: Eip712Domain, - executor_mock: (ExecutorMock, EscrowStorage, QueryAppraisals), - checks: Vec, + executor_mock: ExecutorFixture, ) { - let (executor, escrow_storage, query_appraisal_storage) = executor_mock; + let ExecutorFixture { + checks, + executor, + escrow_storage, + query_appraisals, + .. + } = executor_mock; // give receipt 5 second variance for min start time - let _starting_min_timestamp = get_current_timestamp_u64_ns().unwrap() - 500000000; - let _receipt_auditor = ReceiptAuditor::new(domain_separator.clone(), executor); + let starting_min_timestamp = get_current_timestamp_u64_ns().unwrap() - 500000000; + let receipt_auditor = ReceiptAuditor::new(domain_separator.clone(), executor); let query_value = 20u128; let signed_receipt = EIP712SignedMessage::new( @@ -302,13 +332,10 @@ async fn standard_lifetime_valid_receipt( .await .insert(keys.1, query_value + 500); // appraise query - query_appraisal_storage - .write() - .await - .insert(query_id, query_value); + query_appraisals.write().await.insert(query_id, query_value); let received_receipt = ReceivedReceipt::new(signed_receipt, query_id, &checks); - let _receipt_id = 0u64; + let receipt_id = 0u64; let received_receipt = match received_receipt { ReceivedReceipt::Checking(checking) => checking,