diff --git a/tap_core/src/adapters/mock/executor_mock.rs b/tap_core/src/adapters/mock/executor_mock.rs index 7a807c33..72e08fca 100644 --- a/tap_core/src/adapters/mock/executor_mock.rs +++ b/tap_core/src/adapters/mock/executor_mock.rs @@ -5,8 +5,8 @@ use crate::adapters::escrow_adapter::EscrowAdapter; use crate::adapters::receipt_storage_adapter::{ safe_truncate_receipts, ReceiptDelete, ReceiptRead, ReceiptStore, StoredReceipt, }; -use crate::checks::TimestampCheck; use crate::eip_712_signed_message::MessageId; +use crate::tap_receipt::checks::TimestampCheck; use crate::tap_receipt::ReceivedReceipt; use crate::{ adapters::rav_storage_adapter::{RAVRead, RAVStore}, diff --git a/tap_core/src/adapters/test/escrow_adapter_test.rs b/tap_core/src/adapters/test/escrow_adapter_test.rs index 18c28fd5..c088c897 100644 --- a/tap_core/src/adapters/test/escrow_adapter_test.rs +++ b/tap_core/src/adapters/test/escrow_adapter_test.rs @@ -13,7 +13,7 @@ mod escrow_adapter_unit_test { use crate::{ adapters::{escrow_adapter::EscrowAdapter, executor_mock::ExecutorMock}, - checks::TimestampCheck, + tap_receipt::checks::TimestampCheck, }; #[fixture] diff --git a/tap_core/src/adapters/test/rav_storage_adapter_test.rs b/tap_core/src/adapters/test/rav_storage_adapter_test.rs index 3b51999b..324c596c 100644 --- a/tap_core/src/adapters/test/rav_storage_adapter_test.rs +++ b/tap_core/src/adapters/test/rav_storage_adapter_test.rs @@ -13,7 +13,7 @@ mod rav_storage_adapter_unit_test { use ethers::signers::{LocalWallet, MnemonicBuilder}; use rstest::*; - use crate::checks::TimestampCheck; + use crate::tap_receipt::checks::TimestampCheck; use crate::{ adapters::{ executor_mock::ExecutorMock, diff --git a/tap_core/src/adapters/test/receipt_storage_adapter_test.rs b/tap_core/src/adapters/test/receipt_storage_adapter_test.rs index 35073488..383827fd 100644 --- a/tap_core/src/adapters/test/receipt_storage_adapter_test.rs +++ b/tap_core/src/adapters/test/receipt_storage_adapter_test.rs @@ -9,7 +9,7 @@ mod receipt_storage_adapter_unit_test { use std::str::FromStr; use std::sync::{Arc, RwLock}; - use crate::checks::TimestampCheck; + use crate::tap_receipt::checks::TimestampCheck; use crate::{ adapters::{executor_mock::ExecutorMock, receipt_storage_adapter::ReceiptStore}, eip_712_signed_message::EIP712SignedMessage, diff --git a/tap_core/src/lib.rs b/tap_core/src/lib.rs index fd61aabc..af67e6be 100644 --- a/tap_core/src/lib.rs +++ b/tap_core/src/lib.rs @@ -12,7 +12,6 @@ use alloy_sol_types::eip712_domain; use thiserror::Error; pub mod adapters; -pub mod checks; pub mod eip_712_signed_message; mod error; pub mod receipt_aggregate_voucher; diff --git a/tap_core/src/tap_manager/manager.rs b/tap_core/src/tap_manager/manager.rs index c332e969..fc3512f8 100644 --- a/tap_core/src/tap_manager/manager.rs +++ b/tap_core/src/tap_manager/manager.rs @@ -10,11 +10,11 @@ use crate::{ rav_storage_adapter::{RAVRead, RAVStore}, receipt_storage_adapter::{ReceiptDelete, ReceiptRead, ReceiptStore}, }, - checks::Checks, receipt_aggregate_voucher::ReceiptAggregateVoucher, tap_receipt::{ - CategorizedReceiptsWithState, Failed, ReceiptAuditor, ReceiptWithId, ReceiptWithState, - ReceivedReceipt, Reserved, + checks::{BatchTimestampCheck, CheckBatch, Checks, UniqueCheck}, + CategorizedReceiptsWithState, Failed, ReceiptAuditor, ReceiptWithState, ReceivedReceipt, + Reserved, }, Error, }; @@ -141,11 +141,21 @@ where mut reserved_receipts, } = received_receipts.into(); - for received_receipt in checking_receipts.into_iter() { - let ReceiptWithId { - receipt, - receipt_id: _, - } = received_receipt; + let checking_receipts = checking_receipts + .into_iter() + .map(|receipt| receipt.receipt) + .collect::>(); + + // check for timestamp + let (checking_receipts, already_failed) = + BatchTimestampCheck(min_timestamp_ns).check_batch(checking_receipts); + failed_receipts.extend(already_failed); + + // check for uniqueness + let (checking_receipts, already_failed) = UniqueCheck.check_batch(checking_receipts); + failed_receipts.extend(already_failed); + + for receipt in checking_receipts.into_iter() { let receipt = receipt.finalize_receipt_checks(&self.checks).await; match receipt { diff --git a/tap_core/src/tap_manager/test/manager_test.rs b/tap_core/src/tap_manager/test/manager_test.rs index d7b3c872..080cbd40 100644 --- a/tap_core/src/tap_manager/test/manager_test.rs +++ b/tap_core/src/tap_manager/test/manager_test.rs @@ -17,10 +17,12 @@ use crate::{ executor_mock::{EscrowStorage, ExecutorMock, QueryAppraisals}, receipt_storage_adapter::ReceiptRead, }, - checks::{mock::get_full_list_of_checks, Checks, TimestampCheck}, eip_712_signed_message::EIP712SignedMessage, get_current_timestamp_u64_ns, tap_eip712_domain, - tap_receipt::Receipt, + tap_receipt::{ + checks::{mock::get_full_list_of_checks, Checks, TimestampCheck}, + Receipt, + }, }; #[fixture] diff --git a/tap_core/src/checks/mod.rs b/tap_core/src/tap_receipt/checks.rs similarity index 72% rename from tap_core/src/checks/mod.rs rename to tap_core/src/tap_receipt/checks.rs index 7a50c969..5205e8cd 100644 --- a/tap_core/src/checks/mod.rs +++ b/tap_core/src/tap_receipt/checks.rs @@ -3,10 +3,13 @@ use crate::tap_receipt::{Checking, ReceiptError, ReceiptWithState}; use std::{ + collections::HashSet, ops::Deref, sync::{Arc, RwLock}, }; +use super::Failed; + pub type ReceiptCheck = Arc; pub type CheckResult = anyhow::Result<()>; @@ -32,9 +35,14 @@ pub trait Check { async fn check(&self, receipt: &ReceiptWithState) -> CheckResult; } -#[async_trait::async_trait] pub trait CheckBatch { - async fn check_batch(&self, receipts: &[ReceiptWithState]) -> Vec; + fn check_batch( + &self, + receipts: Vec>, + ) -> ( + Vec>, + Vec>, + ); } #[derive(Debug)] @@ -70,6 +78,59 @@ impl Check for TimestampCheck { } } +/// Timestamp Check verifies if the receipt is **greater or equal** than the minimum timestamp provided. +pub struct BatchTimestampCheck(pub u64); + +impl CheckBatch for BatchTimestampCheck { + fn check_batch( + &self, + receipts: Vec>, + ) -> ( + Vec>, + Vec>, + ) { + let (mut checking, mut failed) = (vec![], vec![]); + for receipt in receipts.into_iter() { + let receipt_timestamp_ns = receipt.signed_receipt().message.timestamp_ns; + let min_timestamp_ns = self.0; + if receipt_timestamp_ns >= min_timestamp_ns { + checking.push(receipt); + } else { + failed.push(receipt.perform_state_error(ReceiptError::InvalidTimestamp { + received_timestamp: receipt_timestamp_ns, + timestamp_min: min_timestamp_ns, + })); + } + } + (checking, failed) + } +} + +pub struct UniqueCheck; + +impl CheckBatch for UniqueCheck { + fn check_batch( + &self, + receipts: Vec>, + ) -> ( + Vec>, + Vec>, + ) { + let mut signatures: HashSet = HashSet::new(); + let (mut checking, mut failed) = (vec![], vec![]); + + for received_receipt in receipts.into_iter() { + let signature = received_receipt.signed_receipt.signature; + if signatures.insert(signature) { + checking.push(received_receipt); + } else { + failed.push(received_receipt.perform_state_error(ReceiptError::NonUniqueReceipt)); + } + } + (checking, failed) + } +} + #[cfg(feature = "mock")] pub mod mock { @@ -96,26 +157,6 @@ pub mod mock { ] } - struct UniqueCheck; - - #[async_trait::async_trait] - impl CheckBatch for UniqueCheck { - async fn check_batch(&self, receipts: &[ReceiptWithState]) -> Vec { - let mut signatures: HashSet = HashSet::new(); - let mut results = Vec::new(); - - for received_receipt in receipts { - let signature = received_receipt.signed_receipt.signature; - if signatures.insert(signature) { - results.push(Ok(())); - } else { - results.push(Err(ReceiptError::NonUniqueReceipt.into())); - } - } - results - } - } - struct ValueCheck { query_appraisals: Arc>>, } diff --git a/tap_core/src/tap_receipt/mod.rs b/tap_core/src/tap_receipt/mod.rs index 7503ec8c..dbceb141 100644 --- a/tap_core/src/tap_receipt/mod.rs +++ b/tap_core/src/tap_receipt/mod.rs @@ -1,6 +1,7 @@ // Copyright 2023-, Semiotic AI, Inc. // SPDX-License-Identifier: Apache-2.0 +pub mod checks; mod receipt; mod receipt_auditor; mod received_receipt; diff --git a/tap_core/src/tap_receipt/received_receipt.rs b/tap_core/src/tap_receipt/received_receipt.rs index 65454931..bbf73217 100644 --- a/tap_core/src/tap_receipt/received_receipt.rs +++ b/tap_core/src/tap_receipt/received_receipt.rs @@ -18,8 +18,8 @@ use serde::{Deserialize, Serialize}; use super::{receipt_auditor::ReceiptAuditor, Receipt, ReceiptError, ReceiptResult}; use crate::{ adapters::{escrow_adapter::EscrowAdapter, receipt_storage_adapter::StoredReceipt}, - checks::ReceiptCheck, eip_712_signed_message::EIP712SignedMessage, + tap_receipt::checks::ReceiptCheck, }; #[derive(Debug, Clone)] @@ -236,7 +236,7 @@ impl ReceiptWithState where S: ReceiptState, { - fn perform_state_error(self, error: ReceiptError) -> ReceiptWithState { + pub(super) fn perform_state_error(self, error: ReceiptError) -> ReceiptWithState { ReceiptWithState { signed_receipt: self.signed_receipt, _state: Failed { error }, 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 8c74ef60..c36846e0 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 @@ -14,10 +14,12 @@ use rstest::*; use crate::{ adapters::executor_mock::{EscrowStorage, ExecutorMock, QueryAppraisals}, - checks::{mock::get_full_list_of_checks, ReceiptCheck, TimestampCheck}, eip_712_signed_message::EIP712SignedMessage, tap_eip712_domain, - tap_receipt::{Receipt, ReceiptAuditor, ReceivedReceipt}, + tap_receipt::{ + checks::{mock::get_full_list_of_checks, ReceiptCheck, TimestampCheck}, + Receipt, ReceiptAuditor, ReceivedReceipt, + }, }; #[fixture] diff --git a/tap_integration_tests/tests/indexer_mock/mod.rs b/tap_integration_tests/tests/indexer_mock/mod.rs index 221c0798..16cb1f67 100644 --- a/tap_integration_tests/tests/indexer_mock/mod.rs +++ b/tap_integration_tests/tests/indexer_mock/mod.rs @@ -22,8 +22,8 @@ use tap_core::{ rav_storage_adapter::{RAVRead, RAVStore}, receipt_storage_adapter::{ReceiptRead, ReceiptStore}, }, - checks::Checks, tap_manager::{Manager, SignedRAV, SignedReceipt}, + tap_receipt::checks::Checks, }; /// Rpc trait represents a JSON-RPC server that has a single async method `request`. /// This method is designed to handle incoming JSON-RPC requests. diff --git a/tap_integration_tests/tests/showcase.rs b/tap_integration_tests/tests/showcase.rs index 881d9964..dc388121 100644 --- a/tap_integration_tests/tests/showcase.rs +++ b/tap_integration_tests/tests/showcase.rs @@ -25,11 +25,13 @@ use rstest::*; use tap_aggregator::{jsonrpsee_helpers, server as agg_server}; use tap_core::{ adapters::executor_mock::{ExecutorMock, QueryAppraisals}, - checks::{mock::get_full_list_of_checks, Checks, TimestampCheck}, eip_712_signed_message::{EIP712SignedMessage, MessageId}, tap_eip712_domain, tap_manager::SignedRAV, - tap_receipt::Receipt, + tap_receipt::{ + checks::{mock::get_full_list_of_checks, Checks, TimestampCheck}, + Receipt, + }, }; use crate::indexer_mock;