Skip to content
Merged
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
87 changes: 0 additions & 87 deletions tap_core/src/manager/adapters/escrow.rs

This file was deleted.

4 changes: 2 additions & 2 deletions tap_core/src/manager/adapters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
//! allows for easy integration with various storage solutions and verification
//! procedures, thereby making the library adaptable to a wide range of use cases.

mod escrow;
mod rav;
mod receipt;
mod signature;

pub use escrow::EscrowHandler;
pub use rav::*;
pub use receipt::*;
pub use signature::SignatureChecker;
46 changes: 46 additions & 0 deletions tap_core/src/manager/adapters/signature.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2023-, Semiotic AI, Inc.
// SPDX-License-Identifier: Apache-2.0

use alloy::{dyn_abi::Eip712Domain, primitives::Address, sol_types::SolStruct};
use async_trait::async_trait;

use crate::{signed_message::EIP712SignedMessage, Error};

/// Manages the escrow operations
///
/// # Example
///
/// For example code see [crate::manager::context::memory::EscrowStorage]

#[async_trait]
pub trait SignatureChecker: Send + Sync {
/// Defines the user-specified error type.
///
/// This error type should implement the `Error` and `Debug` traits from
/// the standard library.
/// Errors of this type are returned to the user when an operation fails.
type AdapterError: std::error::Error + std::fmt::Debug + Send + Sync + 'static;

/// Verifies the signer of the receipt
async fn verify_signer(&self, signer_address: Address) -> Result<bool, Self::AdapterError>;

/// Checks if the signed message has a sender signature
async fn check_signature<T: SolStruct + Sync>(
&self,
signed_message: &EIP712SignedMessage<T>,
domain_separator: &Eip712Domain,
) -> Result<(), Error> {
let recovered_address = signed_message.recover_signer(domain_separator)?;
if self
.verify_signer(recovered_address)
.await
.map_err(|e| Error::FailedToVerifySigner(e.to_string()))?
{
Ok(())
} else {
Err(Error::InvalidRecoveredSigner {
address: recovered_address,
})
}
}
}
12 changes: 1 addition & 11 deletions tap_core/src/manager/context/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,18 +241,8 @@ impl InMemoryContext {
}

#[async_trait]
impl EscrowHandler for InMemoryContext {
impl SignatureChecker for InMemoryContext {
type AdapterError = InMemoryError;
async fn get_available_escrow(&self, sender_id: Address) -> Result<u128, Self::AdapterError> {
self.escrow(sender_id)
}
async fn subtract_escrow(
&self,
sender_id: Address,
value: u128,
) -> Result<(), Self::AdapterError> {
self.reduce_escrow(sender_id, value)
}

async fn verify_signer(&self, signer_address: Address) -> Result<bool, Self::AdapterError> {
Ok(self
Expand Down
34 changes: 13 additions & 21 deletions tap_core/src/manager/tap_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@

use alloy::dyn_abi::Eip712Domain;

use super::adapters::{EscrowHandler, RAVRead, RAVStore, ReceiptDelete, ReceiptRead, ReceiptStore};
use super::adapters::{
RAVRead, RAVStore, ReceiptDelete, ReceiptRead, ReceiptStore, SignatureChecker,
};
use crate::{
rav::{RAVRequest, ReceiptAggregateVoucher, SignedRAV},
receipt::{
checks::{CheckBatch, CheckList, TimestampCheck, UniqueCheck},
state::{Failed, Reserved},
state::{Checked, Failed},
Context, ReceiptError, ReceiptWithState, SignedReceipt,
},
Error,
Expand Down Expand Up @@ -42,7 +44,7 @@ impl<E> Manager<E> {

impl<E> Manager<E>
where
E: RAVStore + EscrowHandler,
E: RAVStore + SignatureChecker,
{
/// Verify `signed_rav` matches all values on `expected_rav`, and that `signed_rav` has a valid signer.
///
Expand All @@ -56,7 +58,7 @@ where
signed_rav: SignedRAV,
) -> std::result::Result<(), Error> {
self.context
.check_rav_signature(&signed_rav, &self.domain_separator)
.check_signature(&signed_rav, &self.domain_separator)
.await?;

if signed_rav.message != expected_rav {
Expand Down Expand Up @@ -95,7 +97,7 @@ where

impl<E> Manager<E>
where
E: ReceiptRead + EscrowHandler,
E: ReceiptRead + SignatureChecker,
{
async fn collect_receipts(
&self,
Expand All @@ -105,7 +107,7 @@ where
limit: Option<u64>,
) -> Result<
(
Vec<ReceiptWithState<Reserved>>,
Vec<ReceiptWithState<Checked>>,
Vec<ReceiptWithState<Failed>>,
),
Error,
Expand All @@ -126,9 +128,8 @@ where
source_error: anyhow::Error::new(err),
})?;

let mut awaiting_reserve_receipts = vec![];
let mut checked_receipts = vec![];
let mut failed_receipts = vec![];
let mut reserved_receipts = vec![];

// check for timestamp
let (checking_receipts, already_failed) =
Expand All @@ -146,27 +147,18 @@ where
.map_err(|e| Error::ReceiptError(ReceiptError::RetryableCheck(e)))?;

match receipt {
Ok(checked) => awaiting_reserve_receipts.push(checked),
Err(failed) => failed_receipts.push(failed),
}
}
for checked in awaiting_reserve_receipts {
match checked
.check_and_reserve_escrow(&self.context, &self.domain_separator)
.await
{
Ok(reserved) => reserved_receipts.push(reserved),
Ok(checked) => checked_receipts.push(checked),
Err(failed) => failed_receipts.push(failed),
}
}

Ok((reserved_receipts, failed_receipts))
Ok((checked_receipts, failed_receipts))
}
}

impl<E> Manager<E>
where
E: ReceiptRead + RAVRead + EscrowHandler,
E: ReceiptRead + RAVRead + SignatureChecker,
{
/// Completes remaining checks on all receipts up to
/// (current time - `timestamp_buffer_ns`). Returns them in two lists
Expand Down Expand Up @@ -210,7 +202,7 @@ where
}

fn generate_expected_rav(
receipts: &[ReceiptWithState<Reserved>],
receipts: &[ReceiptWithState<Checked>],
previous_rav: Option<SignedRAV>,
) -> Result<ReceiptAggregateVoucher, Error> {
if receipts.is_empty() {
Expand Down
4 changes: 2 additions & 2 deletions tap_core/src/rav/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use crate::{
rav::{ReceiptAggregateVoucher, SignedRAV},
receipt::{
state::{Failed, Reserved},
state::{Checked, Failed},
ReceiptWithState,
},
Error,
Expand All @@ -14,7 +14,7 @@ use crate::{
#[derive(Debug)]
pub struct RAVRequest {
/// List of checked and reserved receipts to aggregate
pub valid_receipts: Vec<ReceiptWithState<Reserved>>,
pub valid_receipts: Vec<ReceiptWithState<Checked>>,
/// Optional previous RAV to aggregate with
pub previous_rav: Option<SignedRAV>,
/// List of failed receipt used to log invalid receipts
Expand Down
33 changes: 3 additions & 30 deletions tap_core/src/receipt/received_receipt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,11 @@
//! This module is useful for managing and tracking the state of received receipts, as well as
//! their progress through various checks and stages of inclusion in RAV requests and received RAVs.

use alloy::dyn_abi::Eip712Domain;

use super::{checks::CheckError, Context, Receipt, ReceiptError, ReceiptResult, SignedReceipt};
use crate::{
manager::adapters::EscrowHandler,
receipt::{
checks::ReceiptCheck,
state::{AwaitingReserve, Checking, Failed, ReceiptState, Reserved},
state::{Checked, Checking, Failed, ReceiptState},
},
signed_message::EIP712SignedMessage,
};
Expand Down Expand Up @@ -50,30 +47,6 @@ where
pub(crate) _state: S,
}

impl ReceiptWithState<AwaitingReserve> {
/// Perform the checks implemented by the context and reserve escrow if
/// all checks pass
///
/// Returns a [`ReceiptWithState<Reserved>`] if successful, otherwise
/// returns a [`ReceiptWithState<Failed>`]
pub async fn check_and_reserve_escrow<E>(
self,
context: &E,
domain_separator: &Eip712Domain,
) -> ResultReceipt<Reserved>
where
E: EscrowHandler,
{
match context
.check_and_reserve_escrow(&self, domain_separator)
.await
{
Ok(_) => Ok(self.perform_state_changes(Reserved)),
Err(e) => Err(self.perform_state_error(e)),
}
}
}

impl ReceiptWithState<Checking> {
/// Creates a new `ReceiptWithState` in the `Checking` state
pub fn new(signed_receipt: SignedReceipt) -> ReceiptWithState<Checking> {
Expand Down Expand Up @@ -115,14 +88,14 @@ impl ReceiptWithState<Checking> {
mut self,
ctx: &Context,
checks: &[ReceiptCheck],
) -> Result<ResultReceipt<AwaitingReserve>, String> {
) -> Result<ResultReceipt<Checked>, String> {
let all_checks_passed = self.perform_checks(ctx, checks).await;
if let Err(ReceiptError::RetryableCheck(e)) = all_checks_passed {
Err(e.to_string())
} else if let Err(e) = all_checks_passed {
Ok(Err(self.perform_state_error(e)))
} else {
let checked = self.perform_state_changes(AwaitingReserve);
let checked = self.perform_state_changes(Checked);
Ok(Ok(checked))
}
}
Expand Down
10 changes: 2 additions & 8 deletions tap_core/src/receipt/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,12 @@ pub struct Failed {
pub error: ReceiptError,
}

/// AwaitingReserve state represents a receipt that has passed all checks
/// and is awaiting escrow reservation.
#[derive(Debug, Clone)]
pub struct AwaitingReserve;

/// Reserved state represents a receipt that has successfully reserved escrow.
#[derive(Debug, Clone)]
pub struct Reserved;
pub struct Checked;

/// Trait for the different states a receipt can be in.
pub trait ReceiptState {}
impl ReceiptState for Checking {}
impl ReceiptState for AwaitingReserve {}
impl ReceiptState for Reserved {}
impl ReceiptState for Checked {}
impl ReceiptState for Failed {}
Loading
Loading