Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): enable user custom check flows #179

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 73 additions & 27 deletions tap_core/src/tap_manager/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
receipt_storage_adapter::ReceiptStorageAdapter,
},
receipt_aggregate_voucher::ReceiptAggregateVoucher,
tap_receipt::{ReceiptAuditor, ReceiptCheck, ReceivedReceipt},
tap_receipt::{ReceiptAuditor, ReceiptCheck, ReceiptState, ReceivedReceipt},
Error,
};

Expand Down Expand Up @@ -177,16 +177,52 @@ impl<
/// Returns [`Error::TimestampRangeError`] if the max timestamp of the previous RAV is greater than the min timestamp. Caused by timestamp buffer being too large, or requests coming too soon.
///
pub async fn create_rav_request(&self, timestamp_buffer_ns: u64) -> Result<RAVRequest, Error> {
let previous_rav = self.get_previous_rav().await?;
let min_timestamp_ns = previous_rav
.as_ref()
.map(|rav| rav.message.timestamp_ns + 1)
.unwrap_or(0);
let (previous_rav, received_receipts_with_ids) = self
.collect_receipts_for_rav_request(timestamp_buffer_ns)
.await?;

let (valid_receipts, invalid_receipts) = self
.collect_receipts(timestamp_buffer_ns, min_timestamp_ns)
let received_receipts = self
.finalize_receipt_checks(received_receipts_with_ids)
.await?;

self.create_rav_request_from_receipts_and_rav(received_receipts, previous_rav)
.await
}

/// Creates a RAV request, an expected RAV, a list of valid receipts (included in the RAV request) and list of
/// invalid receipts (omitted from the RAV request) from given received receipts and a previous RAV.
///
/// Checks that all given received receipts' mandatory checks have been completed before creating RAV request.
///
pub async fn create_rav_request_from_receipts_and_rav(
&self,
received_receipts: Vec<ReceivedReceipt>,
previous_rav: Option<SignedRAV>,
) -> Result<RAVRequest, Error> {
// Check that all mandatory checks have been completed before creating RAV request
for received_receipt in &received_receipts {
match received_receipt.state {
ReceiptState::AwaitingReserveEscrow
| ReceiptState::Accepted
| ReceiptState::Complete
| ReceiptState::Failed => Ok(()),
_ => Err(Error::InvalidStateForRequestedAction {
state: received_receipt.state.to_string(),
}),
}?;
}

let mut valid_receipts = Vec::<SignedReceipt>::new();
let mut invalid_receipts = Vec::<SignedReceipt>::new();

for received_receipt in received_receipts {
if received_receipt.is_accepted() {
valid_receipts.push(received_receipt.signed_receipt);
} else {
invalid_receipts.push(received_receipt.signed_receipt);
}
}

let expected_rav = Self::generate_expected_rav(&valid_receipts, previous_rav.clone())?;

self.receipt_auditor
Expand All @@ -212,11 +248,18 @@ impl<
Ok(previous_rav)
}

async fn collect_receipts(
/// Collects all receipts that are newer than the previous RAV, and older than (current time - `timestamp_buffer_ns`).
/// Returns the previous RAV and the list of received receipts and corresponding storage IDs.
pub async fn collect_receipts_for_rav_request(
&self,
timestamp_buffer_ns: u64,
min_timestamp_ns: u64,
) -> Result<(Vec<SignedReceipt>, Vec<SignedReceipt>), Error> {
) -> Result<(Option<SignedRAV>, Vec<(u64, ReceivedReceipt)>), Error> {
let previous_rav = self.get_previous_rav().await?;
let min_timestamp_ns = previous_rav
.as_ref()
.map(|rav| rav.message.timestamp_ns + 1)
.unwrap_or(0);

let max_timestamp_ns = crate::get_current_timestamp_u64_ns()? - timestamp_buffer_ns;

if min_timestamp_ns > max_timestamp_ns {
Expand All @@ -225,29 +268,32 @@ impl<
max_timestamp_ns,
});
}
let received_receipts = self
.receipt_storage_adapter
.retrieve_receipts_in_timestamp_range(min_timestamp_ns..max_timestamp_ns)
.await
.map_err(|err| Error::AdapterError {
source_error: anyhow::Error::new(err),
})?;
Ok((
previous_rav,
self.receipt_storage_adapter
.retrieve_receipts_in_timestamp_range(min_timestamp_ns..max_timestamp_ns)
.await
.map_err(|err| Error::AdapterError {
source_error: anyhow::Error::new(err),
})?,
))
}

let mut accepted_signed_receipts = Vec::<SignedReceipt>::new();
let mut failed_signed_receipts = Vec::<SignedReceipt>::new();
/// Completes remaining checks on all receipts in `received_receipts_with_ids` and returns them.
pub async fn finalize_receipt_checks(
&self,
received_receipts_with_ids: Vec<(u64, ReceivedReceipt)>,
) -> Result<Vec<ReceivedReceipt>, Error> {
let mut received_receipts: Vec<ReceivedReceipt> = Vec::new();

for (receipt_id, mut received_receipt) in received_receipts {
for (receipt_id, mut received_receipt) in received_receipts_with_ids {
received_receipt
.finalize_receipt_checks(receipt_id, &self.receipt_auditor)
.await?;
if received_receipt.is_accepted() {
accepted_signed_receipts.push(received_receipt.signed_receipt);
} else {
failed_signed_receipts.push(received_receipt.signed_receipt);
}
received_receipts.push(received_receipt);
}

Ok((accepted_signed_receipts, failed_signed_receipts))
Ok(received_receipts)
}

fn generate_expected_rav(
Expand Down
8 changes: 7 additions & 1 deletion tap_core/src/tap_receipt/received_receipt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,13 @@ impl ReceivedReceipt {
self.update_state();
}

pub(crate) fn update_check(
/// Update the state of a receipt check, should be called when a check is completed.
///
/// Note: the function is public to let library users update the state of a check if they are using a different
/// checking mechanism than the one provided by the library, such as running batch checks before a RAV request.
///
/// Todo: consider refactoring to make this function private again.
pub fn update_check(
&mut self,
check: &ReceiptCheck,
result: Option<super::ReceiptResult<()>>,
Expand Down
Loading