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
17 changes: 7 additions & 10 deletions tap_aggregator/src/aggregator/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub fn check_and_aggregate_receipts(
wallet: &PrivateKeySigner,
accepted_addresses: &HashSet<Address>,
) -> Result<Eip712SignedMessage<ReceiptAggregateVoucher>> {
check_signatures_unique(domain_separator, receipts)?;
check_signatures_unique(receipts)?;

// Check that the receipts are signed by an accepted signer address
receipts.par_iter().try_for_each(|receipt| {
Expand Down Expand Up @@ -93,17 +93,14 @@ fn check_allocation_id(
Ok(())
}

fn check_signatures_unique(
domain_separator: &Eip712Domain,
receipts: &[Eip712SignedMessage<Receipt>],
) -> Result<()> {
fn check_signatures_unique(receipts: &[Eip712SignedMessage<Receipt>]) -> Result<()> {
let mut receipt_signatures = HashSet::new();
for receipt in receipts.iter() {
let signature = receipt.unique_id(domain_separator)?;
let signature = receipt.unique_id();
if !receipt_signatures.insert(signature) {
return Err(tap_core::Error::DuplicateReceiptSignature(format!(
"{:?}",
receipt.unique_id(domain_separator)?
receipt.unique_id()
))
.into());
}
Expand Down Expand Up @@ -221,7 +218,7 @@ mod tests {

// This should return an error because the signatures are different
// but the messages are the same, which if allowed would present a security vulnerability
let result = check_signatures_unique(&domain_separator, &receipts);
let result = check_signatures_unique(&receipts);

// The result should be an error because the malleated signature is not treated as unique
// and is detected as a duplicate
Expand All @@ -246,7 +243,7 @@ mod tests {
receipts.push(receipt.clone());
receipts.push(receipt);

let res = check_signatures_unique(&domain_separator, &receipts);
let res = check_signatures_unique(&receipts);
assert!(res.is_err());
}

Expand All @@ -273,7 +270,7 @@ mod tests {
.unwrap(),
];

let res = check_signatures_unique(&domain_separator, &receipts);
let res = check_signatures_unique(&receipts);
assert!(res.is_ok());
}

Expand Down
15 changes: 6 additions & 9 deletions tap_aggregator/src/aggregator/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub fn check_and_aggregate_receipts(
wallet: &PrivateKeySigner,
accepted_addresses: &HashSet<Address>,
) -> Result<Eip712SignedMessage<ReceiptAggregateVoucher>> {
check_signatures_unique(domain_separator, receipts)?;
check_signatures_unique(receipts)?;

// Check that the receipts are signed by an accepted signer address
receipts.par_iter().try_for_each(|receipt| {
Expand Down Expand Up @@ -148,17 +148,14 @@ fn check_allocation_id(
Ok(())
}

fn check_signatures_unique(
domain_separator: &Eip712Domain,
receipts: &[Eip712SignedMessage<Receipt>],
) -> Result<()> {
fn check_signatures_unique(receipts: &[Eip712SignedMessage<Receipt>]) -> Result<()> {
let mut receipt_signatures = HashSet::new();
for receipt in receipts.iter() {
let signature = receipt.unique_id(domain_separator)?;
let signature = receipt.unique_id();
if !receipt_signatures.insert(signature) {
return Err(tap_core::Error::DuplicateReceiptSignature(format!(
"{:?}",
receipt.unique_id(domain_separator)?
receipt.unique_id()
))
.into());
}
Expand Down Expand Up @@ -254,7 +251,7 @@ mod tests {
receipts.push(receipt.clone());
receipts.push(receipt);

let res = super::check_signatures_unique(&domain_separator, &receipts);
let res = super::check_signatures_unique(&receipts);
assert!(res.is_err());
}

Expand Down Expand Up @@ -284,7 +281,7 @@ mod tests {
.unwrap(),
];

let res = super::check_signatures_unique(&domain_separator, &receipts);
let res = super::check_signatures_unique(&receipts);
assert!(res.is_ok());
}

Expand Down
7 changes: 3 additions & 4 deletions tap_core/src/manager/tap_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,12 @@ where
let mut failed_receipts = vec![];

// check for timestamp
let (checking_receipts, already_failed) = TimestampCheck(min_timestamp_ns)
.check_batch(&self.domain_separator, checking_receipts)?;
let (checking_receipts, already_failed) =
TimestampCheck(min_timestamp_ns).check_batch(checking_receipts)?;
failed_receipts.extend(already_failed);

// check for uniqueness
let (checking_receipts, already_failed) =
UniqueCheck.check_batch(&self.domain_separator, checking_receipts)?;
let (checking_receipts, already_failed) = UniqueCheck.check_batch(checking_receipts)?;
failed_receipts.extend(already_failed);

for receipt in checking_receipts.into_iter() {
Expand Down
12 changes: 6 additions & 6 deletions tap_core/tests/manager_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ async fn manager_verify_and_store_varying_initial_checks(
&signer,
)
.unwrap();
let query_id = signed_receipt.unique_hash(&domain_separator).unwrap();
let query_id = signed_receipt.unique_hash();
query_appraisals.write().unwrap().insert(query_id, value);
escrow_storage
.write()
Expand Down Expand Up @@ -182,7 +182,7 @@ async fn manager_create_rav_request_all_valid_receipts(
&signer,
)
.unwrap();
let query_id = signed_receipt.unique_hash(&domain_separator).unwrap();
let query_id = signed_receipt.unique_hash();
stored_signed_receipts.push(signed_receipt.clone());
query_appraisals.write().unwrap().insert(query_id, value);
assert!(manager
Expand Down Expand Up @@ -277,7 +277,7 @@ async fn manager_create_multiple_rav_requests_all_valid_receipts(
&signer,
)
.unwrap();
let query_id = signed_receipt.unique_hash(&domain_separator).unwrap();
let query_id = signed_receipt.unique_hash();
stored_signed_receipts.push(signed_receipt.clone());
query_appraisals.write().unwrap().insert(query_id, value);
assert!(manager
Expand Down Expand Up @@ -321,7 +321,7 @@ async fn manager_create_multiple_rav_requests_all_valid_receipts(
)
.unwrap();

let query_id = signed_receipt.unique_hash(&domain_separator).unwrap();
let query_id = signed_receipt.unique_hash();
stored_signed_receipts.push(signed_receipt.clone());
query_appraisals.write().unwrap().insert(query_id, value);
assert!(manager
Expand Down Expand Up @@ -389,7 +389,7 @@ async fn manager_create_multiple_rav_requests_all_valid_receipts_consecutive_tim
receipt.timestamp_ns = starting_min_timestamp + query_id + 1;
let signed_receipt = Eip712SignedMessage::new(&domain_separator, receipt, &signer).unwrap();

let query_id = signed_receipt.unique_hash(&domain_separator).unwrap();
let query_id = signed_receipt.unique_hash();
stored_signed_receipts.push(signed_receipt.clone());
query_appraisals.write().unwrap().insert(query_id, value);
assert!(manager
Expand Down Expand Up @@ -436,7 +436,7 @@ async fn manager_create_multiple_rav_requests_all_valid_receipts_consecutive_tim
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, &signer).unwrap();
let query_id = signed_receipt.unique_hash(&domain_separator).unwrap();
let query_id = signed_receipt.unique_hash();
stored_signed_receipts.push(signed_receipt.clone());
query_appraisals.write().unwrap().insert(query_id, value);
assert!(manager
Expand Down
6 changes: 3 additions & 3 deletions tap_core/tests/received_receipt_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ async fn partial_then_full_check_valid_receipt(
)
.unwrap();

let query_id = signed_receipt.unique_hash(&domain_separator).unwrap();
let query_id = signed_receipt.unique_hash();

// add escrow for sender
escrow_storage
Expand Down Expand Up @@ -156,7 +156,7 @@ async fn partial_then_finalize_valid_receipt(
&signer,
)
.unwrap();
let query_id = signed_receipt.unique_hash(&domain_separator).unwrap();
let query_id = signed_receipt.unique_hash();

// add escrow for sender
escrow_storage
Expand Down Expand Up @@ -203,7 +203,7 @@ async fn standard_lifetime_valid_receipt(
)
.unwrap();

let query_id = signed_receipt.unique_hash(&domain_separator).unwrap();
let query_id = signed_receipt.unique_hash();

// add escrow for sender
escrow_storage
Expand Down
21 changes: 4 additions & 17 deletions tap_eip712_message/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
use serde::{Deserialize, Serialize};
use thegraph_core::alloy::{
dyn_abi::Eip712Domain,
primitives::{keccak256, Address, Signature},
primitives::{Address, Signature},
signers::{local::PrivateKeySigner, SignerSync},
sol_types::SolStruct,
};
Expand Down Expand Up @@ -105,21 +105,8 @@ impl<M: SolStruct> Eip712SignedMessage<M> {
Ok(recovered_address)
}

/// Generate a uniqueness identifier using both the message content and the recovered signer
pub fn unique_hash(&self, domain_separator: &Eip712Domain) -> Result<MessageId, Eip712Error> {
// Get the hash of just the message content
let message_hash = self.message.eip712_hash_struct();

// Recover the signer address
let signer = self.recover_signer(domain_separator)?;

// Create a new hash combining both the message hash and the signer address
let mut input = Vec::with_capacity(32 + 20); // 32 bytes for hash, 20 bytes for address
input.extend_from_slice(&message_hash.0);
input.extend_from_slice(signer.as_ref());

let combined_hash = keccak256(&input);

Ok(MessageId(*combined_hash))
/// Use this as a simple key for testing
pub fn unique_hash(&self) -> MessageId {
MessageId(self.message.eip712_hash_struct().into())
}
}
15 changes: 3 additions & 12 deletions tap_receipt/src/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ use std::{
};

use tap_eip712_message::Eip712Error;
use thegraph_core::alloy::dyn_abi::Eip712Domain;

use super::{
state::{Checking, Failed},
Expand Down Expand Up @@ -97,7 +96,6 @@ type CheckBatchResponse<Rcpt> = (
pub trait CheckBatch<Rcpt> {
fn check_batch(
&self,
domain_separator: &Eip712Domain,
receipts: Vec<ReceiptWithState<Checking, Rcpt>>,
) -> Result<CheckBatchResponse<Rcpt>, Eip712Error>;
}
Expand Down Expand Up @@ -157,7 +155,6 @@ where
{
fn check_batch(
&self,
_domain_separator: &Eip712Domain,
receipts: Vec<ReceiptWithState<Checking, Rcpt>>,
) -> Result<CheckBatchResponse<Rcpt>, Eip712Error> {
let (mut checking, mut failed) = (vec![], vec![]);
Expand Down Expand Up @@ -189,14 +186,13 @@ where
{
fn check_batch(
&self,
domain_separator: &Eip712Domain,
receipts: Vec<ReceiptWithState<Checking, Rcpt>>,
) -> Result<CheckBatchResponse<Rcpt>, Eip712Error> {
let mut signatures = HashSet::new();
let (mut checking, mut failed) = (vec![], vec![]);

for received_receipt in receipts.into_iter() {
let unique_id = received_receipt.receipt.unique_id(domain_separator)?;
let unique_id = received_receipt.receipt.unique_id();
if signatures.insert(unique_id) {
checking.push(received_receipt);
} else {
Expand Down Expand Up @@ -277,10 +273,7 @@ mod tests {
let signed_receipt_2 = create_signed_receipt_with_custom_value(15);
let signed_receipt_copy = signed_receipt.clone();
let receipts_batch = vec![signed_receipt, signed_receipt_2, signed_receipt_copy];
let domain_separator = create_test_domain_separator();
let (valid_receipts, invalid_receipts) = UniqueCheck
.check_batch(&domain_separator, receipts_batch)
.unwrap();
let (valid_receipts, invalid_receipts) = UniqueCheck.check_batch(receipts_batch).unwrap();
assert_eq!(valid_receipts.len(), 2);
assert_eq!(invalid_receipts.len(), 1);
}
Expand All @@ -290,12 +283,10 @@ mod tests {
let signed_receipt = create_signed_receipt_with_custom_value(10);
let signed_receipt_2 = create_signed_receipt_with_custom_value(15);

let domain_separator = create_test_domain_separator();

let receipts_batch = vec![signed_receipt.clone(), signed_receipt_2];
let min_time_stamp = signed_receipt.receipt.message.timestamp_ns + 1;
let (valid_receipts, invalid_receipts) = TimestampCheck(min_time_stamp)
.check_batch(&domain_separator, receipts_batch)
.check_batch(receipts_batch)
.unwrap();
assert_eq!(valid_receipts.len(), 1);
assert_eq!(invalid_receipts.len(), 1);
Expand Down
12 changes: 6 additions & 6 deletions tap_receipt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ pub mod state;

pub use error::ReceiptError;
pub use received_receipt::ReceiptWithState;
use tap_eip712_message::{Eip712Error, Eip712SignedMessage, MessageId};
use thegraph_core::alloy::{dyn_abi::Eip712Domain, sol_types::SolStruct};
use tap_eip712_message::{Eip712SignedMessage, SignatureBytes, SignatureBytesExt};
use thegraph_core::alloy::sol_types::SolStruct;

/// Result type for receipt
pub type ReceiptResult<T> = Result<T, ReceiptError>;
Expand All @@ -45,7 +45,7 @@ pub trait WithValueAndTimestamp {
/// Extension that allows UniqueCheck for any SolStruct receipt
pub trait WithUniqueId {
type Output: Eq + std::hash::Hash;
fn unique_id(&self, domain_separator: &Eip712Domain) -> Result<Self::Output, Eip712Error>;
fn unique_id(&self) -> Self::Output;
}

impl<T> WithValueAndTimestamp for Eip712SignedMessage<T>
Expand All @@ -65,9 +65,9 @@ impl<T> WithUniqueId for Eip712SignedMessage<T>
where
T: SolStruct,
{
type Output = MessageId;
type Output = SignatureBytes;

fn unique_id(&self, domain_separator: &Eip712Domain) -> Result<Self::Output, Eip712Error> {
self.unique_hash(domain_separator)
fn unique_id(&self) -> Self::Output {
self.signature.normalized_s().get_signature_bytes()
}
}