From 1dada3e32a62ce632c0425151960cbe8c914cb3b Mon Sep 17 00:00:00 2001 From: Gustavo Inacio Date: Thu, 26 Dec 2024 20:13:22 +0100 Subject: [PATCH] feat: add tap v2 Signed-off-by: Gustavo Inacio --- tap_aggregator/src/aggregator.rs | 336 +++++++++++++++--- tap_aggregator/src/server.rs | 72 ++-- .../timeline_aggretion_protocol_benchmark.rs | 47 ++- tap_core/src/error.rs | 14 +- tap_core/src/lib.rs | 61 +++- tap_core/src/manager/context/memory.rs | 14 +- tap_core/src/manager/mod.rs | 2 +- tap_core/src/manager/tap_manager.rs | 8 +- tap_core/src/rav.rs | 28 +- tap_core/src/receipt/checks.rs | 7 +- tap_core/src/receipt/receipt_sol.rs | 58 ++- tap_core/src/signed_message.rs | 2 +- tap_core/tests/manager_test.rs | 83 ++++- tap_core/tests/rav_test.rs | 51 ++- tap_core/tests/receipt_test.rs | 19 +- tap_core/tests/received_receipt_test.rs | 39 +- ...v_test__check_for_rav_serialization-2.snap | 11 +- ...rav_test__check_for_rav_serialization.snap | 100 +++--- tap_integration_tests/tests/showcase.rs | 24 +- 19 files changed, 745 insertions(+), 231 deletions(-) diff --git a/tap_aggregator/src/aggregator.rs b/tap_aggregator/src/aggregator.rs index a6e4cb6d..3635ce76 100644 --- a/tap_aggregator/src/aggregator.rs +++ b/tap_aggregator/src/aggregator.rs @@ -46,28 +46,63 @@ pub fn check_and_aggregate_receipts( check_receipt_timestamps(receipts, previous_rav.as_ref())?; // Get the allocation id from the first receipt, return error if there are no receipts - let allocation_id = match receipts.first() { - Some(receipt) => receipt.message.allocation_id, + let (payer, data_service, service_provider) = match receipts.first() { + Some(receipt) => ( + receipt.message.payer, + receipt.message.data_service, + receipt.message.service_provider, + ), None => return Err(tap_core::Error::NoValidReceiptsForRAVRequest.into()), }; - // Check that the receipts all have the same allocation id - check_allocation_id(receipts, allocation_id)?; + // Check that the receipts all have the same payer + check_payer(receipts, payer)?; + + // Check that the receipts all have the same service_provider + check_data_service(receipts, data_service)?; + + // Check that the receipts all have the same service_provider + check_service_provider(receipts, service_provider)?; // Check that the rav has the correct allocation id if let Some(previous_rav) = &previous_rav { - let prev_id = previous_rav.message.allocationId; - if prev_id != allocation_id { - return Err(tap_core::Error::RavAllocationIdMismatch { - prev_id: format!("{prev_id:#X}"), - new_id: format!("{allocation_id:#X}"), + let prev_payer = previous_rav.message.payer; + if prev_payer != payer { + return Err(tap_core::Error::RavPayerMismatch { + prev_id: format!("{prev_payer:#X}"), + new_id: format!("{payer:#X}"), + } + .into()); + } + + let prev_data_service = previous_rav.message.dataService; + if prev_data_service != data_service { + return Err(tap_core::Error::RavDataServiceMismatch { + prev_id: format!("{prev_payer:#X}"), + new_id: format!("{payer:#X}"), + } + .into()); + } + + let prev_service_provider = previous_rav.message.serviceProvider; + + if prev_service_provider != service_provider { + return Err(tap_core::Error::RavServiceProviderMismatch { + prev_id: format!("{prev_payer:#X}"), + new_id: format!("{payer:#X}"), } .into()); } } // Aggregate the receipts - let rav = ReceiptAggregateVoucher::aggregate_receipts(allocation_id, receipts, previous_rav)?; + let rav = ReceiptAggregateVoucher::aggregate_receipts( + payer, + data_service, + service_provider, + receipts, + previous_rav, + )?; // Sign the rav and return Ok(EIP712SignedMessage::new(domain_separator, rav, wallet)?) @@ -87,13 +122,36 @@ fn check_signature_is_from_one_of_addresses( Ok(()) } -fn check_allocation_id( +fn check_payer(receipts: &[EIP712SignedMessage], payer: Address) -> Result<()> { + for receipt in receipts.iter() { + let receipt = &receipt.message; + if receipt.payer != payer { + return Err(tap_core::Error::RavAllocationIdNotUniform.into()); + } + } + Ok(()) +} + +fn check_data_service( receipts: &[EIP712SignedMessage], - allocation_id: Address, + data_service: Address, ) -> Result<()> { for receipt in receipts.iter() { let receipt = &receipt.message; - if receipt.allocation_id != allocation_id { + if receipt.data_service != data_service { + return Err(tap_core::Error::RavAllocationIdNotUniform.into()); + } + } + Ok(()) +} + +fn check_service_provider( + receipts: &[EIP712SignedMessage], + service_provider: Address, +) -> Result<()> { + for receipt in receipts.iter() { + let receipt = &receipt.message; + if receipt.service_provider != service_provider { return Err(tap_core::Error::RavAllocationIdNotUniform.into()); } } @@ -137,9 +195,11 @@ fn check_receipt_timestamps( #[cfg(test)] mod tests { - use std::str::FromStr; - - use alloy::{dyn_abi::Eip712Domain, primitives::Address, signers::local::PrivateKeySigner}; + use alloy::{ + dyn_abi::Eip712Domain, + primitives::{address, Address, Bytes}, + signers::local::PrivateKeySigner, + }; use rstest::*; use crate::aggregator; @@ -153,13 +213,23 @@ mod tests { } #[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(), - ] + fn payer() -> Address { + address!("abababababababababababababababababababab") + } + + #[fixture] + fn data_service() -> Address { + address!("deaddeaddeaddeaddeaddeaddeaddeaddeaddead") + } + + #[fixture] + fn service_provider() -> Address { + address!("beefbeefbeefbeefbeefbeefbeefbeefbeefbeef") + } + + #[fixture] + fn other_address() -> Address { + address!("1234567890abcdef1234567890abcdef12345678") } #[fixture] @@ -171,14 +241,16 @@ mod tests { #[test] fn check_signatures_unique_fail( keys: (PrivateKeySigner, Address), - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, domain_separator: Eip712Domain, ) { // Create the same receipt twice (replay attack) let mut receipts = Vec::new(); let receipt = EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], 42).unwrap(), + Receipt::new(payer, data_service, service_provider, 42).unwrap(), &keys.0, ) .unwrap(); @@ -193,20 +265,22 @@ mod tests { #[test] fn check_signatures_unique_ok( keys: (PrivateKeySigner, Address), - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, domain_separator: Eip712Domain, ) { // Create 2 different receipts let receipts = vec![ EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], 42).unwrap(), + Receipt::new(payer, data_service, service_provider, 42).unwrap(), &keys.0, ) .unwrap(), EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], 43).unwrap(), + Receipt::new(payer, data_service, service_provider, 43).unwrap(), &keys.0, ) .unwrap(), @@ -221,7 +295,9 @@ mod tests { /// Test that a receipt with a timestamp greater then the rav timestamp passes fn check_receipt_timestamps( keys: (PrivateKeySigner, Address), - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, domain_separator: Eip712Domain, ) { // Create receipts with consecutive timestamps @@ -232,7 +308,9 @@ mod tests { EIP712SignedMessage::new( &domain_separator, Receipt { - allocation_id: allocation_ids[0], + payer, + data_service, + service_provider, timestamp_ns: i, nonce: 0, value: 42, @@ -247,9 +325,12 @@ mod tests { let rav = EIP712SignedMessage::new( &domain_separator, tap_core::rav::ReceiptAggregateVoucher { - allocationId: allocation_ids[0], + payer, + dataService: data_service, + serviceProvider: service_provider, timestampNs: receipt_timestamp_range.clone().min().unwrap() - 1, valueAggregate: 42, + metadata: Bytes::new(), }, &keys.0, ) @@ -261,9 +342,12 @@ mod tests { let rav = EIP712SignedMessage::new( &domain_separator, tap_core::rav::ReceiptAggregateVoucher { - allocationId: allocation_ids[0], + payer, + dataService: data_service, + serviceProvider: service_provider, timestampNs: receipt_timestamp_range.clone().min().unwrap(), valueAggregate: 42, + metadata: Bytes::new(), }, &keys.0, ) @@ -275,9 +359,12 @@ mod tests { let rav = EIP712SignedMessage::new( &domain_separator, tap_core::rav::ReceiptAggregateVoucher { - allocationId: allocation_ids[0], + payer, + dataService: data_service, + serviceProvider: service_provider, timestampNs: receipt_timestamp_range.clone().max().unwrap() + 1, valueAggregate: 42, + metadata: Bytes::new(), }, &keys.0, ) @@ -287,69 +374,222 @@ mod tests { #[rstest] #[test] - /// Test check_allocation_id with 2 receipts that have the correct allocation id - /// and 1 receipt that has the wrong allocation id - fn check_allocation_id_fail( + /// Test check_service_provider with 2 receipts that have the correct service_provicer + /// and 1 receipt that has the wrong service_provider + fn check_service_provider_fail( + keys: (PrivateKeySigner, Address), + payer: Address, + data_service: Address, + service_provider: Address, + other_address: Address, + domain_separator: Eip712Domain, + ) { + let receipts = vec![ + EIP712SignedMessage::new( + &domain_separator, + Receipt::new(payer, data_service, service_provider, 42).unwrap(), + &keys.0, + ) + .unwrap(), + EIP712SignedMessage::new( + &domain_separator, + Receipt::new(payer, data_service, service_provider, 43).unwrap(), + &keys.0, + ) + .unwrap(), + EIP712SignedMessage::new( + &domain_separator, + Receipt::new(payer, data_service, other_address, 44).unwrap(), + &keys.0, + ) + .unwrap(), + ]; + + let res = aggregator::check_service_provider(&receipts, service_provider); + + assert!(res.is_err()); + } + + #[rstest] + #[test] + /// Test check_service_provider with 3 receipts that have the correct service provider + fn check_service_provider_ok( + keys: (PrivateKeySigner, Address), + payer: Address, + data_service: Address, + service_provider: Address, + domain_separator: Eip712Domain, + ) { + let receipts = vec![ + EIP712SignedMessage::new( + &domain_separator, + Receipt::new(payer, data_service, service_provider, 42).unwrap(), + &keys.0, + ) + .unwrap(), + EIP712SignedMessage::new( + &domain_separator, + Receipt::new(payer, data_service, service_provider, 43).unwrap(), + &keys.0, + ) + .unwrap(), + EIP712SignedMessage::new( + &domain_separator, + Receipt::new(payer, data_service, service_provider, 44).unwrap(), + &keys.0, + ) + .unwrap(), + ]; + + let res = aggregator::check_service_provider(&receipts, service_provider); + + assert!(res.is_ok()); + } + + #[rstest] + #[test] + /// Test check_payer with 2 receipts that have the correct payer + /// and 1 receipt that has the wrong payer + fn check_payer_fail( + keys: (PrivateKeySigner, Address), + payer: Address, + data_service: Address, + service_provider: Address, + other_address: Address, + domain_separator: Eip712Domain, + ) { + let receipts = vec![ + EIP712SignedMessage::new( + &domain_separator, + Receipt::new(payer, data_service, service_provider, 42).unwrap(), + &keys.0, + ) + .unwrap(), + EIP712SignedMessage::new( + &domain_separator, + Receipt::new(payer, data_service, service_provider, 43).unwrap(), + &keys.0, + ) + .unwrap(), + EIP712SignedMessage::new( + &domain_separator, + Receipt::new(other_address, data_service, service_provider, 44).unwrap(), + &keys.0, + ) + .unwrap(), + ]; + + let res = aggregator::check_payer(&receipts, payer); + + assert!(res.is_err()); + } + + #[rstest] + #[test] + /// Test check_payer with 3 receipts that have the correct payer + fn check_payer_ok( + keys: (PrivateKeySigner, Address), + payer: Address, + data_service: Address, + service_provider: Address, + domain_separator: Eip712Domain, + ) { + let receipts = vec![ + EIP712SignedMessage::new( + &domain_separator, + Receipt::new(payer, data_service, service_provider, 42).unwrap(), + &keys.0, + ) + .unwrap(), + EIP712SignedMessage::new( + &domain_separator, + Receipt::new(payer, data_service, service_provider, 43).unwrap(), + &keys.0, + ) + .unwrap(), + EIP712SignedMessage::new( + &domain_separator, + Receipt::new(payer, data_service, service_provider, 44).unwrap(), + &keys.0, + ) + .unwrap(), + ]; + + let res = aggregator::check_payer(&receipts, payer); + + assert!(res.is_ok()); + } + + #[rstest] + #[test] + /// Test check_data_service with 2 receipts that have the correct data service + /// and 1 receipt that has the wrong data service + fn check_data_service_fail( keys: (PrivateKeySigner, Address), - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, + other_address: Address, domain_separator: Eip712Domain, ) { let receipts = vec![ EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], 42).unwrap(), + Receipt::new(payer, data_service, service_provider, 42).unwrap(), &keys.0, ) .unwrap(), EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], 43).unwrap(), + Receipt::new(payer, data_service, service_provider, 43).unwrap(), &keys.0, ) .unwrap(), EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[1], 44).unwrap(), + Receipt::new(payer, other_address, service_provider, 44).unwrap(), &keys.0, ) .unwrap(), ]; - let res = aggregator::check_allocation_id(&receipts, allocation_ids[0]); + let res = aggregator::check_data_service(&receipts, data_service); assert!(res.is_err()); } #[rstest] #[test] - /// Test check_allocation_id with 3 receipts that have the correct allocation id - fn check_allocation_id_ok( + /// Test check_data_service with 3 receipts that have the correct data service + fn check_data_service_ok( keys: (PrivateKeySigner, Address), - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, domain_separator: Eip712Domain, ) { let receipts = vec![ EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], 42).unwrap(), + Receipt::new(payer, data_service, service_provider, 42).unwrap(), &keys.0, ) .unwrap(), EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], 43).unwrap(), + Receipt::new(payer, data_service, service_provider, 43).unwrap(), &keys.0, ) .unwrap(), EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], 44).unwrap(), + Receipt::new(payer, data_service, service_provider, 44).unwrap(), &keys.0, ) .unwrap(), ]; - let res = aggregator::check_allocation_id(&receipts, allocation_ids[0]); + let res = aggregator::check_data_service(&receipts, data_service); assert!(res.is_ok()); } diff --git a/tap_aggregator/src/server.rs b/tap_aggregator/src/server.rs index 0ff03d3b..4dcd3e99 100644 --- a/tap_aggregator/src/server.rs +++ b/tap_aggregator/src/server.rs @@ -241,9 +241,12 @@ pub async fn run_server( #[allow(clippy::too_many_arguments)] mod tests { use std::collections::HashSet; - use std::str::FromStr; - use alloy::{dyn_abi::Eip712Domain, primitives::Address, signers::local::PrivateKeySigner}; + use alloy::{ + dyn_abi::Eip712Domain, + primitives::{address, Address}, + signers::local::PrivateKeySigner, + }; use jsonrpsee::{core::client::ClientT, http_client::HttpClientBuilder, rpc_params}; use rand::prelude::*; use rand::seq::SliceRandom; @@ -268,13 +271,18 @@ mod tests { } #[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(), - ] + fn payer() -> Address { + address!("abababababababababababababababababababab") + } + + #[fixture] + fn data_service() -> Address { + address!("deaddeaddeaddeaddeaddeaddeaddeaddeaddead") + } + + #[fixture] + fn service_provider() -> Address { + address!("beefbeefbeefbeefbeefbeefbeefbeefbeefbeef") } #[fixture] @@ -343,7 +351,9 @@ mod tests { http_request_size_limit: u32, http_response_size_limit: u32, http_max_concurrent_connections: u32, - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, #[case] values: Vec, #[values("0.0")] api_version: &str, #[values(0, 1, 2)] random_seed: u64, @@ -382,7 +392,7 @@ mod tests { receipts.push( EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], value).unwrap(), + Receipt::new(payer, data_service, service_provider, value).unwrap(), &all_wallets.choose(&mut rng).unwrap().wallet, ) .unwrap(), @@ -401,11 +411,18 @@ mod tests { let remote_rav = res.data; - let local_rav = - ReceiptAggregateVoucher::aggregate_receipts(allocation_ids[0], &receipts, None) - .unwrap(); + let local_rav = ReceiptAggregateVoucher::aggregate_receipts( + payer, + data_service, + service_provider, + &receipts, + None, + ) + .unwrap(); - assert!(remote_rav.message.allocationId == local_rav.allocationId); + assert!(remote_rav.message.payer == local_rav.payer); + assert!(remote_rav.message.dataService == local_rav.dataService); + assert!(remote_rav.message.serviceProvider == local_rav.serviceProvider); assert!(remote_rav.message.timestampNs == local_rav.timestampNs); assert!(remote_rav.message.valueAggregate == local_rav.valueAggregate); @@ -424,7 +441,9 @@ mod tests { http_request_size_limit: u32, http_response_size_limit: u32, http_max_concurrent_connections: u32, - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, #[case] values: Vec, #[values("0.0")] api_version: &str, #[values(0, 1, 2, 3, 4)] random_seed: u64, @@ -463,7 +482,7 @@ mod tests { receipts.push( EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], value).unwrap(), + Receipt::new(payer, data_service, service_provider, value).unwrap(), &all_wallets.choose(&mut rng).unwrap().wallet, ) .unwrap(), @@ -472,7 +491,9 @@ mod tests { // Create previous RAV from first half of receipts locally let prev_rav = ReceiptAggregateVoucher::aggregate_receipts( - allocation_ids[0], + payer, + data_service, + service_provider, &receipts[0..receipts.len() / 2], None, ) @@ -512,7 +533,9 @@ mod tests { http_request_size_limit: u32, http_response_size_limit: u32, http_max_concurrent_connections: u32, - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, ) { // The keys that will be used to sign the new RAVs let keys_main = keys(); @@ -538,7 +561,7 @@ mod tests { // Create receipts let receipts = vec![EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], 42).unwrap(), + Receipt::new(payer, data_service, service_provider, 42).unwrap(), &keys_main.wallet, ) .unwrap()]; @@ -594,7 +617,9 @@ mod tests { domain_separator: Eip712Domain, http_response_size_limit: u32, http_max_concurrent_connections: u32, - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, #[values("0.0")] api_version: &str, ) { // The keys that will be used to sign the new RAVs @@ -602,7 +627,7 @@ mod tests { // Set the request byte size limit to a value that easily triggers the HTTP 413 // error. - let http_request_size_limit = 100 * 1024; + let http_request_size_limit = 120 * 1024; // Number of receipts that is just above the number that would fit within the // request size limit. This value is hard-coded here because it supports the @@ -633,7 +658,7 @@ mod tests { receipts.push( EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], u128::MAX / 1000).unwrap(), + Receipt::new(payer, data_service, service_provider, u128::MAX / 1000).unwrap(), &keys_main.wallet, ) .unwrap(), @@ -656,6 +681,7 @@ mod tests { ), ) .await; + println!("{res:?}"); assert!(res.is_ok()); // Create RAV through the JSON-RPC server. diff --git a/tap_core/benches/timeline_aggretion_protocol_benchmark.rs b/tap_core/benches/timeline_aggretion_protocol_benchmark.rs index e76e1d29..ec334fa0 100644 --- a/tap_core/benches/timeline_aggretion_protocol_benchmark.rs +++ b/tap_core/benches/timeline_aggretion_protocol_benchmark.rs @@ -21,13 +21,15 @@ use tap_core::{ pub fn create_and_sign_receipt( domain_separator: &Eip712Domain, - allocation_id: Address, + payer: Address, + data_service: Address, + service_provider: Address, value: u128, wallet: &PrivateKeySigner, ) -> EIP712SignedMessage { EIP712SignedMessage::new( domain_separator, - Receipt::new(allocation_id, value).unwrap(), + Receipt::new(payer, data_service, service_provider, value).unwrap(), wallet, ) .unwrap() @@ -40,21 +42,32 @@ pub fn criterion_benchmark(c: &mut Criterion) { let address = wallet.address(); // Arbitrary values wrapped in black box to avoid compiler optimizing them out - let allocation_id = Address::from_str("0xabababababababababababababababababababab").unwrap(); + let payer = Address::from_str("0xabababababababababababababababababababab").unwrap(); + let data_service = Address::from_str("0xabababababababababababababababababababab").unwrap(); + let service_provider = Address::from_str("0xabababababababababababababababababababab").unwrap(); let value = 12345u128; c.bench_function("Create Receipt", |b| { b.iter(|| { create_and_sign_receipt( black_box(&domain_seperator), - black_box(allocation_id), + black_box(payer), + black_box(data_service), + black_box(service_provider), black_box(value), black_box(&wallet), ) }) }); - let receipt = create_and_sign_receipt(&domain_seperator, allocation_id, value, &wallet); + let receipt = create_and_sign_receipt( + &domain_seperator, + payer, + data_service, + service_provider, + value, + &wallet, + ); c.bench_function("Validate Receipt", |b| { b.iter(|| { @@ -68,7 +81,16 @@ pub fn criterion_benchmark(c: &mut Criterion) { for log_number_of_receipts in 10..30 { let receipts = (0..2 ^ log_number_of_receipts) - .map(|_| create_and_sign_receipt(&domain_seperator, allocation_id, value, &wallet)) + .map(|_| { + create_and_sign_receipt( + &domain_seperator, + payer, + data_service, + service_provider, + value, + &wallet, + ) + }) .collect::>(); rav_group.bench_function( @@ -76,7 +98,9 @@ pub fn criterion_benchmark(c: &mut Criterion) { |b| { b.iter(|| { ReceiptAggregateVoucher::aggregate_receipts( - black_box(allocation_id), + black_box(payer), + black_box(data_service), + black_box(service_provider), black_box(&receipts), black_box(None), ) @@ -86,7 +110,14 @@ pub fn criterion_benchmark(c: &mut Criterion) { let signed_rav = EIP712SignedMessage::new( &domain_seperator, - ReceiptAggregateVoucher::aggregate_receipts(allocation_id, &receipts, None).unwrap(), + ReceiptAggregateVoucher::aggregate_receipts( + payer, + data_service, + service_provider, + &receipts, + None, + ) + .unwrap(), &wallet, ) .unwrap(); diff --git a/tap_core/src/error.rs b/tap_core/src/error.rs index b5d1c562..125caf88 100644 --- a/tap_core/src/error.rs +++ b/tap_core/src/error.rs @@ -47,8 +47,18 @@ pub enum Error { NoValidReceiptsForRAVRequest, /// Error when the previous RAV allocation id does not match the allocation id from the new receipt - #[error("Previous RAV allocation id ({prev_id}) doesn't match the allocation id from the new receipt ({new_id}).")] - RavAllocationIdMismatch { prev_id: String, new_id: String }, + #[error( + "Previous RAV payer ({prev_id}) doesn't match the payer from the new receipt ({new_id})." + )] + RavPayerMismatch { prev_id: String, new_id: String }, + + /// Error when the previous RAV data service does not match the data service from the new receipt + #[error("Previous RAV data_service ({prev_id}) doesn't match the data_service from the new receipt ({new_id}).")] + RavDataServiceMismatch { prev_id: String, new_id: String }, + + /// Error when the previous RAV service provider does not match the service provider from the new receipt + #[error("Previous RAV service_provider ({prev_id}) doesn't match the service_provider from the new receipt ({new_id}).")] + RavServiceProviderMismatch { prev_id: String, new_id: String }, /// Error when all receipts do not have the same allocation id /// diff --git a/tap_core/src/lib.rs b/tap_core/src/lib.rs index eb09fe67..01f6abb6 100644 --- a/tap_core/src/lib.rs +++ b/tap_core/src/lib.rs @@ -60,7 +60,11 @@ pub fn tap_eip712_domain( mod tap_tests { use std::str::FromStr; - use alloy::{dyn_abi::Eip712Domain, primitives::Address, signers::local::PrivateKeySigner}; + use alloy::{ + dyn_abi::Eip712Domain, + primitives::{address, Address}, + signers::local::PrivateKeySigner, + }; use rstest::*; use crate::{ @@ -77,13 +81,18 @@ mod tap_tests { } #[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(), - ] + fn payer() -> Address { + address!("abababababababababababababababababababab") + } + + #[fixture] + fn data_service() -> Address { + address!("deaddeaddeaddeaddeaddeaddeaddeaddeaddead") + } + + #[fixture] + fn service_provider() -> Address { + address!("beefbeefbeefbeefbeefbeefbeefbeefbeefbeef") } #[fixture] @@ -97,7 +106,9 @@ mod tap_tests { #[test] fn signed_rav_is_valid_with_no_previous_rav( keys: (PrivateKeySigner, Address), - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, domain_separator: Eip712Domain, #[case] values: Vec, ) { @@ -107,7 +118,7 @@ mod tap_tests { receipts.push( EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], value).unwrap(), + Receipt::new(payer, data_service, service_provider, value).unwrap(), &keys.0, ) .unwrap(), @@ -116,8 +127,14 @@ mod tap_tests { // Skipping receipts validation in this test, aggregate_receipts assumes receipts are valid. - let rav = ReceiptAggregateVoucher::aggregate_receipts(allocation_ids[0], &receipts, None) - .unwrap(); + let rav = ReceiptAggregateVoucher::aggregate_receipts( + payer, + data_service, + service_provider, + &receipts, + None, + ) + .unwrap(); let signed_rav = EIP712SignedMessage::new(&domain_separator, rav, &keys.0).unwrap(); assert!(signed_rav.recover_signer(&domain_separator).unwrap() == keys.1); } @@ -128,7 +145,9 @@ mod tap_tests { #[test] fn signed_rav_is_valid_with_previous_rav( keys: (PrivateKeySigner, Address), - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, domain_separator: Eip712Domain, #[case] values: Vec, ) { @@ -138,7 +157,7 @@ mod tap_tests { receipts.push( EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], value).unwrap(), + Receipt::new(payer, data_service, service_provider, value).unwrap(), &keys.0, ) .unwrap(), @@ -147,7 +166,9 @@ mod tap_tests { // Create previous RAV from first half of receipts let prev_rav = ReceiptAggregateVoucher::aggregate_receipts( - allocation_ids[0], + payer, + data_service, + service_provider, &receipts[0..receipts.len() / 2], None, ) @@ -157,7 +178,9 @@ mod tap_tests { // Create new RAV from last half of receipts and prev_rav let rav = ReceiptAggregateVoucher::aggregate_receipts( - allocation_ids[0], + payer, + data_service, + service_provider, &receipts[receipts.len() / 2..receipts.len()], Some(signed_prev_rav), ) @@ -171,12 +194,14 @@ mod tap_tests { #[test] fn verify_signature( keys: (PrivateKeySigner, Address), - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, domain_separator: Eip712Domain, ) { let signed_message = EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], 42).unwrap(), + Receipt::new(payer, data_service, service_provider, 42).unwrap(), &keys.0, ) .unwrap(); diff --git a/tap_core/src/manager/context/memory.rs b/tap_core/src/manager/context/memory.rs index 21eff1b7..0b2a3693 100644 --- a/tap_core/src/manager/context/memory.rs +++ b/tap_core/src/manager/context/memory.rs @@ -276,13 +276,13 @@ pub mod checks { pub fn get_full_list_of_checks( domain_separator: Eip712Domain, valid_signers: HashSet
, - allocation_ids: Arc>>, + payers: Arc>>, _query_appraisals: Arc>>, ) -> Vec { vec![ // Arc::new(UniqueCheck ), // Arc::new(ValueCheck { query_appraisals }), - Arc::new(AllocationIdCheck { allocation_ids }), + Arc::new(PayerCheck { payers }), Arc::new(SignatureCheck { domain_separator, valid_signers, @@ -290,16 +290,16 @@ pub mod checks { ] } - struct AllocationIdCheck { - allocation_ids: Arc>>, + struct PayerCheck { + payers: Arc>>, } #[async_trait::async_trait] - impl Check for AllocationIdCheck { + impl Check for PayerCheck { async fn check(&self, _: &Context, receipt: &ReceiptWithState) -> CheckResult { - let received_allocation_id = receipt.signed_receipt().message.allocation_id; + let received_allocation_id = receipt.signed_receipt().message.payer; if self - .allocation_ids + .payers .read() .unwrap() .contains(&received_allocation_id) diff --git a/tap_core/src/manager/mod.rs b/tap_core/src/manager/mod.rs index 7696796e..c065385b 100644 --- a/tap_core/src/manager/mod.rs +++ b/tap_core/src/manager/mod.rs @@ -66,7 +66,7 @@ //! # use tap_core::signed_message::EIP712SignedMessage; //! # let domain_separator = Eip712Domain::default(); //! # let wallet = PrivateKeySigner::random(); -//! # let message = Receipt::new(Address::from([0x11u8; 20]), 100).unwrap(); +//! # let message = Receipt::new(Address::ZERO, Address::ZERO, Address::ZERO, 100).unwrap(); //! //! let receipt = EIP712SignedMessage::new(&domain_separator, message, &wallet).unwrap(); //! diff --git a/tap_core/src/manager/tap_manager.rs b/tap_core/src/manager/tap_manager.rs index 304e4d17..5edf305a 100644 --- a/tap_core/src/manager/tap_manager.rs +++ b/tap_core/src/manager/tap_manager.rs @@ -216,13 +216,17 @@ where if receipts.is_empty() { return Err(Error::NoValidReceiptsForRAVRequest); } - let allocation_id = receipts[0].signed_receipt().message.allocation_id; + let payer = receipts[0].signed_receipt().message.payer; + let service_provider = receipts[0].signed_receipt().message.service_provider; + let data_service = receipts[0].signed_receipt().message.data_service; let receipts = receipts .iter() .map(|rx_receipt| rx_receipt.signed_receipt().clone()) .collect::>(); ReceiptAggregateVoucher::aggregate_receipts( - allocation_id, + payer, + service_provider, + data_service, receipts.as_slice(), previous_rav, ) diff --git a/tap_core/src/rav.rs b/tap_core/src/rav.rs index 78ea2c80..fa8fb416 100644 --- a/tap_core/src/rav.rs +++ b/tap_core/src/rav.rs @@ -41,7 +41,7 @@ mod request; use std::cmp; -use alloy::primitives::Address; +use alloy::primitives::{Address, Bytes}; use alloy::sol; use serde::{Deserialize, Serialize}; @@ -58,14 +58,19 @@ sol! { /// We use camelCase for field names to match the Ethereum ABI encoding #[derive(Debug, Serialize, Deserialize, Eq, PartialEq)] struct ReceiptAggregateVoucher { - /// Unique allocation id this RAV belongs to - address allocationId; - /// Unix Epoch timestamp in nanoseconds (Truncated to 64-bits) - /// corresponding to max timestamp from receipt batch aggregated + // The address of the payer the RAV was issued by + address payer; + // The address of the data service the RAV was issued to + address dataService; + // The address of the service provider the RAV was issued to + address serviceProvider; + // The RAV timestamp, indicating the latest TAP Receipt in the RAV uint64 timestampNs; - /// Aggregated value from receipt batch and any previous RAV provided - /// (truncate to lower bits) + // Total amount owed to the service provider since the beginning of the + // payer-service provider relationship, including all debt that is already paid for. uint128 valueAggregate; + // Arbitrary metadata to extend functionality if a data service requires it + bytes metadata; } } @@ -78,7 +83,9 @@ impl ReceiptAggregateVoucher { /// Returns [`Error::AggregateOverflow`] if any receipt value causes aggregate /// value to overflow pub fn aggregate_receipts( - allocation_id: Address, + payer: Address, + data_service: Address, + service_provider: Address, receipts: &[EIP712SignedMessage], previous_rav: Option>, ) -> crate::Result { @@ -102,9 +109,12 @@ impl ReceiptAggregateVoucher { } Ok(Self { - allocationId: allocation_id, timestampNs: timestamp_max, valueAggregate: value_aggregate, + payer, + dataService: data_service, + serviceProvider: service_provider, + metadata: Bytes::new(), }) } } diff --git a/tap_core/src/receipt/checks.rs b/tap_core/src/receipt/checks.rs index 4820cf8d..40ef5cc3 100644 --- a/tap_core/src/receipt/checks.rs +++ b/tap_core/src/receipt/checks.rs @@ -200,11 +200,11 @@ impl CheckBatch for UniqueCheck { #[cfg(test)] mod tests { - use std::str::FromStr; use std::time::Duration; use std::time::SystemTime; use alloy::dyn_abi::Eip712Domain; + use alloy::primitives::address; use alloy::primitives::Address; use alloy::signers::local::PrivateKeySigner; use alloy::sol_types::eip712_domain; @@ -235,8 +235,9 @@ mod tests { let receipt = EIP712SignedMessage::new( &eip712_domain_separator, Receipt { - allocation_id: Address::from_str("0xabababababababababababababababababababab") - .unwrap(), + payer: address!("abababababababababababababababababababab"), + data_service: address!("abababababababababababababababababababab"), + service_provider: address!("abababababababababababababababababababab"), nonce, timestamp_ns, value, diff --git a/tap_core/src/receipt/receipt_sol.rs b/tap_core/src/receipt/receipt_sol.rs index c7670eba..f16b6567 100644 --- a/tap_core/src/receipt/receipt_sol.rs +++ b/tap_core/src/receipt/receipt_sol.rs @@ -16,8 +16,12 @@ sol! { /// Holds information needed for promise of payment signed with ECDSA #[derive(Debug, Serialize, Deserialize, Eq, PartialEq)] struct Receipt { - /// Unique allocation id this receipt belongs to - address allocation_id; + // The address of the payer the RAV was issued by + address payer; + // The address of the data service the RAV was issued to + address data_service; + // The address of the service provider the RAV was issued to + address service_provider; /// Unix Epoch timestamp in nanoseconds (Truncated to 64-bits) uint64 timestamp_ns; /// Random value used to avoid collisions from multiple receipts with one timestamp @@ -29,11 +33,18 @@ sol! { impl Receipt { /// Returns a receipt with provided values - pub fn new(allocation_id: Address, value: u128) -> crate::Result { + pub fn new( + payer: Address, + data_service: Address, + service_provider: Address, + value: u128, + ) -> crate::Result { let timestamp_ns = crate::get_current_timestamp_u64_ns()?; let nonce = thread_rng().gen::(); Ok(Self { - allocation_id, + payer, + data_service, + service_provider, timestamp_ns, nonce, value, @@ -44,27 +55,34 @@ impl Receipt { #[cfg(test)] mod receipt_unit_test { use super::*; + use alloy::primitives::address; use rstest::*; - use std::str::FromStr; use std::time::{SystemTime, UNIX_EPOCH}; #[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(), - ] + fn payer() -> Address { + address!("abababababababababababababababababababab") + } + + #[fixture] + fn data_service() -> Address { + address!("deaddeaddeaddeaddeaddeaddeaddeaddeaddead") + } + + #[fixture] + fn service_provider() -> Address { + address!("beefbeefbeefbeefbeefbeefbeefbeefbeefbeef") } #[rstest] - fn test_new_receipt(allocation_ids: Vec
) { + fn test_new_receipt(payer: Address, data_service: Address, service_provider: Address) { let value = 1234; - let receipt = Receipt::new(allocation_ids[0], value).unwrap(); + let receipt = Receipt::new(payer, data_service, service_provider, value).unwrap(); - assert_eq!(receipt.allocation_id, allocation_ids[0]); + assert_eq!(receipt.payer, payer); + assert_eq!(receipt.data_service, data_service); + assert_eq!(receipt.service_provider, service_provider); assert_eq!(receipt.value, value); // Check that the timestamp is within a reasonable range @@ -77,11 +95,15 @@ mod receipt_unit_test { } #[rstest] - fn test_unique_nonce_and_timestamp(allocation_ids: Vec
) { + fn test_unique_nonce_and_timestamp( + payer: Address, + data_service: Address, + service_provider: Address, + ) { let value = 1234; - let receipt1 = Receipt::new(allocation_ids[0], value).unwrap(); - let receipt2 = Receipt::new(allocation_ids[0], value).unwrap(); + let receipt1 = Receipt::new(payer, data_service, service_provider, value).unwrap(); + let receipt2 = Receipt::new(payer, data_service, service_provider, value).unwrap(); let now = SystemTime::now() .duration_since(UNIX_EPOCH) .expect("Current system time should be greater than `UNIX_EPOCH`") diff --git a/tap_core/src/signed_message.rs b/tap_core/src/signed_message.rs index a0572d2e..fde0a065 100644 --- a/tap_core/src/signed_message.rs +++ b/tap_core/src/signed_message.rs @@ -16,7 +16,7 @@ //! }; //! # let wallet = PrivateKeySigner::random(); //! # let wallet_address = wallet.address(); -//! # let message = Receipt::new(Address::from([0x11u8; 20]), 100).unwrap(); +//! # let message = Receipt::new(Address::ZERO, Address::ZERO, Address::ZERO, 100).unwrap(); //! //! let signed_message = EIP712SignedMessage::new(&domain_separator, message, &wallet).unwrap(); //! let signer = signed_message.recover_signer(&domain_separator).unwrap(); diff --git a/tap_core/tests/manager_test.rs b/tap_core/tests/manager_test.rs index e8a05082..ea33bd42 100644 --- a/tap_core/tests/manager_test.rs +++ b/tap_core/tests/manager_test.rs @@ -7,7 +7,11 @@ use std::{ time::{SystemTime, UNIX_EPOCH}, }; -use alloy::{dyn_abi::Eip712Domain, primitives::Address, signers::local::PrivateKeySigner}; +use alloy::{ + dyn_abi::Eip712Domain, + primitives::{address, Address, Bytes}, + signers::local::PrivateKeySigner, +}; use anyhow::anyhow; use rstest::*; @@ -48,6 +52,21 @@ fn allocation_ids() -> Vec
{ ] } +#[fixture] +fn payer() -> Address { + address!("abababababababababababababababababababab") +} + +#[fixture] +fn data_service() -> Address { + address!("deaddeaddeaddeaddeaddeaddeaddeaddeaddead") +} + +#[fixture] +fn service_provider() -> Address { + address!("beefbeefbeefbeefbeefbeefbeefbeefbeefbeef") +} + #[fixture] fn sender_ids(signer: PrivateKeySigner) -> (PrivateKeySigner, Vec
) { let address = signer.address(); @@ -116,7 +135,9 @@ fn context( #[rstest] #[tokio::test] async fn manager_verify_and_store_varying_initial_checks( - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, domain_separator: Eip712Domain, context: ContextFixture, ) { @@ -133,7 +154,7 @@ async fn manager_verify_and_store_varying_initial_checks( let value = 20u128; let signed_receipt = EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], value).unwrap(), + Receipt::new(payer, data_service, service_provider, value).unwrap(), &signer, ) .unwrap(); @@ -153,7 +174,9 @@ async fn manager_verify_and_store_varying_initial_checks( #[rstest] #[tokio::test] async fn manager_create_rav_request_all_valid_receipts( - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, domain_separator: Eip712Domain, context: ContextFixture, ) { @@ -176,7 +199,7 @@ async fn manager_create_rav_request_all_valid_receipts( let value = 20u128; let signed_receipt = EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], value).unwrap(), + Receipt::new(payer, data_service, service_provider, value).unwrap(), &signer, ) .unwrap(); @@ -212,7 +235,13 @@ async fn manager_create_rav_request_all_valid_receipts( #[rstest] #[tokio::test] -async fn deny_rav_due_to_wrong_value(domain_separator: Eip712Domain, context: ContextFixture) { +async fn deny_rav_due_to_wrong_value( + domain_separator: Eip712Domain, + payer: Address, + data_service: Address, + service_provider: Address, + context: ContextFixture, +) { let ContextFixture { context, checks, @@ -222,15 +251,21 @@ async fn deny_rav_due_to_wrong_value(domain_separator: Eip712Domain, context: Co let manager = Manager::new(domain_separator.clone(), context, checks); let rav = ReceiptAggregateVoucher { - allocationId: Address::from_str("0xabababababababababababababababababababab").unwrap(), + payer, + dataService: data_service, + serviceProvider: service_provider, timestampNs: 1232442, valueAggregate: 20u128, + metadata: Bytes::new(), }; let rav_wrong_value = ReceiptAggregateVoucher { - allocationId: Address::from_str("0xabababababababababababababababababababab").unwrap(), + payer, + dataService: data_service, + serviceProvider: service_provider, timestampNs: 1232442, valueAggregate: 10u128, + metadata: Bytes::new(), }; let signed_rav_with_wrong_aggregate = @@ -245,7 +280,9 @@ async fn deny_rav_due_to_wrong_value(domain_separator: Eip712Domain, context: Co #[rstest] #[tokio::test] async fn manager_create_multiple_rav_requests_all_valid_receipts( - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, domain_separator: Eip712Domain, context: ContextFixture, ) { @@ -271,7 +308,7 @@ async fn manager_create_multiple_rav_requests_all_valid_receipts( let value = 20u128; let signed_receipt = EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], value).unwrap(), + Receipt::new(payer, data_service, service_provider, value).unwrap(), &signer, ) .unwrap(); @@ -314,7 +351,7 @@ async fn manager_create_multiple_rav_requests_all_valid_receipts( let value = 20u128; let signed_receipt = EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], value).unwrap(), + Receipt::new(payer, data_service, service_provider, value).unwrap(), &signer, ) .unwrap(); @@ -357,7 +394,9 @@ async fn manager_create_multiple_rav_requests_all_valid_receipts( #[rstest] #[tokio::test] async fn manager_create_multiple_rav_requests_all_valid_receipts_consecutive_timestamps( - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, domain_separator: Eip712Domain, #[values(true, false)] remove_old_receipts: bool, context: ContextFixture, @@ -383,7 +422,7 @@ async fn manager_create_multiple_rav_requests_all_valid_receipts_consecutive_tim 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(); + let mut receipt = Receipt::new(payer, data_service, service_provider, value).unwrap(); receipt.timestamp_ns = starting_min_timestamp + query_id + 1; let signed_receipt = EIP712SignedMessage::new(&domain_separator, receipt, &signer).unwrap(); @@ -431,7 +470,7 @@ async fn manager_create_multiple_rav_requests_all_valid_receipts_consecutive_tim stored_signed_receipts.clear(); for query_id in 10..20 { let value = 20u128; - let mut receipt = Receipt::new(allocation_ids[0], value).unwrap(); + let mut receipt = Receipt::new(payer, data_service, service_provider, 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(); @@ -487,7 +526,9 @@ async fn manager_create_multiple_rav_requests_all_valid_receipts_consecutive_tim #[rstest] #[tokio::test] async fn manager_create_rav_and_ignore_invalid_receipts( - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, domain_separator: Eip712Domain, context: ContextFixture, ) { @@ -510,7 +551,9 @@ async fn manager_create_rav_and_ignore_invalid_receipts( //Forcing all receipts but one to be invalid by making all the same for _ in 0..10 { let receipt = Receipt { - allocation_id: allocation_ids[0], + payer, + data_service, + service_provider, timestamp_ns: 1, nonce: 1, value: 20u128, @@ -539,7 +582,9 @@ async fn manager_create_rav_and_ignore_invalid_receipts( #[rstest] #[tokio::test] async fn test_retryable_checks( - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, domain_separator: Eip712Domain, context: ContextFixture, ) { @@ -590,7 +635,9 @@ async fn test_retryable_checks( let mut stored_signed_receipts = Vec::new(); for i in 0..10 { let receipt = Receipt { - allocation_id: allocation_ids[0], + payer, + data_service, + service_provider, timestamp_ns: i + 1, nonce: i, value: 20u128, diff --git a/tap_core/tests/rav_test.rs b/tap_core/tests/rav_test.rs index 17149e46..2bb612ba 100644 --- a/tap_core/tests/rav_test.rs +++ b/tap_core/tests/rav_test.rs @@ -1,11 +1,13 @@ // Copyright 2023-, Semiotic AI, Inc. // SPDX-License-Identifier: Apache-2.0 -use std::collections::HashMap; -use std::sync::RwLock; -use std::{str::FromStr, sync::Arc}; +use std::{ + collections::HashMap, + sync::{Arc, RwLock}, +}; use alloy::dyn_abi::Eip712Domain; +use alloy::primitives::address; #[allow(deprecated)] use alloy::primitives::{Address, PrimitiveSignature, Signature}; use alloy::signers::local::{coins_bip39::English, MnemonicBuilder, PrivateKeySigner}; @@ -42,7 +44,9 @@ fn context() -> InMemoryContext { #[rstest] fn check_for_rav_serialization(domain_separator: Eip712Domain) { - let allocation_id = Address::from_str("0xabababababababababababababababababababab").unwrap(); + let payer = address!("abababababababababababababababababababab"); + let data_service = address!("abababababababababababababababababababab"); + let service_provider = address!("abababababababababababababababababababab"); let wallet = MnemonicBuilder::::default() .phrase("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about") .build() @@ -53,7 +57,9 @@ fn check_for_rav_serialization(domain_separator: Eip712Domain) { EIP712SignedMessage::new( &domain_separator, Receipt { - allocation_id, + payer, + data_service, + service_provider, value, nonce: value as u64, timestamp_ns: value as u64, @@ -66,7 +72,14 @@ fn check_for_rav_serialization(domain_separator: Eip712Domain) { let signed_rav = EIP712SignedMessage::new( &domain_separator, - ReceiptAggregateVoucher::aggregate_receipts(allocation_id, &receipts, None).unwrap(), + ReceiptAggregateVoucher::aggregate_receipts( + payer, + data_service, + service_provider, + &receipts, + None, + ) + .unwrap(), &wallet, ) .unwrap(); @@ -90,7 +103,9 @@ fn check_for_rav_serialization(domain_separator: Eip712Domain) { async fn rav_storage_adapter_test(domain_separator: Eip712Domain, context: InMemoryContext) { let wallet = PrivateKeySigner::random(); - let allocation_id = Address::from_str("0xabababababababababababababababababababab").unwrap(); + let payer = address!("abababababababababababababababababababab"); + let data_service = address!("abababababababababababababababababababab"); + let service_provider = address!("abababababababababababababababababababab"); // Create receipts let mut receipts = Vec::new(); @@ -98,7 +113,7 @@ async fn rav_storage_adapter_test(domain_separator: Eip712Domain, context: InMem receipts.push( EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_id, value).unwrap(), + Receipt::new(payer, data_service, service_provider, value).unwrap(), &wallet, ) .unwrap(), @@ -107,7 +122,14 @@ async fn rav_storage_adapter_test(domain_separator: Eip712Domain, context: InMem let signed_rav = EIP712SignedMessage::new( &domain_separator, - ReceiptAggregateVoucher::aggregate_receipts(allocation_id, &receipts, None).unwrap(), + ReceiptAggregateVoucher::aggregate_receipts( + payer, + data_service, + service_provider, + &receipts, + None, + ) + .unwrap(), &wallet, ) .unwrap(); @@ -126,7 +148,7 @@ async fn rav_storage_adapter_test(domain_separator: Eip712Domain, context: InMem receipts.push( EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_id, value).unwrap(), + Receipt::new(payer, data_service, service_provider, value).unwrap(), &wallet, ) .unwrap(), @@ -135,7 +157,14 @@ async fn rav_storage_adapter_test(domain_separator: Eip712Domain, context: InMem let signed_rav = EIP712SignedMessage::new( &domain_separator, - ReceiptAggregateVoucher::aggregate_receipts(allocation_id, &receipts, None).unwrap(), + ReceiptAggregateVoucher::aggregate_receipts( + payer, + data_service, + service_provider, + &receipts, + None, + ) + .unwrap(), &wallet, ) .unwrap(); diff --git a/tap_core/tests/receipt_test.rs b/tap_core/tests/receipt_test.rs index a507bc7e..82bd72c0 100644 --- a/tap_core/tests/receipt_test.rs +++ b/tap_core/tests/receipt_test.rs @@ -1,12 +1,11 @@ use alloy::dyn_abi::Eip712Domain; -use alloy::primitives::Address; +use alloy::primitives::{address, Address}; use alloy::signers::local::PrivateKeySigner; // Copyright 2023-, Semiotic AI, Inc. // SPDX-License-Identifier: Apache-2.0 use rand::seq::SliceRandom; use rand::thread_rng; use std::collections::HashMap; -use std::str::FromStr; use std::sync::{Arc, RwLock}; use tap_core::manager::context::memory::InMemoryContext; use tap_core::receipt::{state::Checking, ReceiptWithState}; @@ -43,14 +42,16 @@ fn context() -> InMemoryContext { async fn receipt_adapter_test(domain_separator: Eip712Domain, mut context: InMemoryContext) { let wallet = PrivateKeySigner::random(); - let allocation_id = Address::from_str("0xabababababababababababababababababababab").unwrap(); + let payer = address!("abababababababababababababababababababab"); + let data_service = address!("abababababababababababababababababababab"); + let service_provider = address!("abababababababababababababababababababab"); // Create receipts let value = 100u128; let received_receipt = ReceiptWithState::new( EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_id, value).unwrap(), + Receipt::new(payer, data_service, service_provider, value).unwrap(), &wallet, ) .unwrap(), @@ -82,7 +83,9 @@ async fn receipt_adapter_test(domain_separator: Eip712Domain, mut context: InMem async fn multi_receipt_adapter_test(domain_separator: Eip712Domain, mut context: InMemoryContext) { let wallet = PrivateKeySigner::random(); - let allocation_id = Address::from_str("0xabababababababababababababababababababab").unwrap(); + let payer = address!("abababababababababababababababababababab"); + let data_service = address!("abababababababababababababababababababab"); + let service_provider = address!("abababababababababababababababababababab"); // Create receipts let mut received_receipts = Vec::new(); @@ -90,7 +93,7 @@ async fn multi_receipt_adapter_test(domain_separator: Eip712Domain, mut context: received_receipts.push(ReceiptWithState::new( EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_id, value).unwrap(), + Receipt::new(payer, data_service, service_provider, value).unwrap(), &wallet, ) .unwrap(), @@ -168,7 +171,9 @@ fn safe_truncate_receipts_test( EIP712SignedMessage::new( &domain_separator, Receipt { - allocation_id: Address::ZERO, + payer: Address::ZERO, + data_service: Address::ZERO, + service_provider: Address::ZERO, timestamp_ns: *timestamp, nonce: 0, value: 0, diff --git a/tap_core/tests/received_receipt_test.rs b/tap_core/tests/received_receipt_test.rs index 2b6c6e0b..74e816c0 100644 --- a/tap_core/tests/received_receipt_test.rs +++ b/tap_core/tests/received_receipt_test.rs @@ -7,7 +7,11 @@ use std::{ sync::{Arc, RwLock}, }; -use alloy::{dyn_abi::Eip712Domain, primitives::Address, signers::local::PrivateKeySigner}; +use alloy::{ + dyn_abi::Eip712Domain, + primitives::{address, Address}, + signers::local::PrivateKeySigner, +}; use rstest::*; use tap_core::{ manager::context::memory::{ @@ -36,6 +40,21 @@ fn allocation_ids() -> Vec
{ ] } +#[fixture] +fn payer() -> Address { + address!("abababababababababababababababababababab") +} + +#[fixture] +fn data_service() -> Address { + address!("deaddeaddeaddeaddeaddeaddeaddeaddeaddead") +} + +#[fixture] +fn service_provider() -> Address { + address!("beefbeefbeefbeefbeefbeefbeefbeefbeefbeef") +} + #[fixture] fn sender_ids(signer: PrivateKeySigner) -> (PrivateKeySigner, Vec
) { let address = signer.address(); @@ -104,7 +123,9 @@ fn context( #[tokio::test] async fn partial_then_full_check_valid_receipt( domain_separator: Eip712Domain, - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, context: ContextFixture, ) { let ContextFixture { @@ -118,7 +139,7 @@ async fn partial_then_full_check_valid_receipt( let query_value = 20u128; let signed_receipt = EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], query_value).unwrap(), + Receipt::new(payer, data_service, service_provider, query_value).unwrap(), &signer, ) .unwrap(); @@ -147,7 +168,9 @@ async fn partial_then_full_check_valid_receipt( #[rstest] #[tokio::test] async fn partial_then_finalize_valid_receipt( - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, domain_separator: Eip712Domain, context: ContextFixture, ) { @@ -163,7 +186,7 @@ async fn partial_then_finalize_valid_receipt( let query_value = 20u128; let signed_receipt = EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], query_value).unwrap(), + Receipt::new(payer, data_service, service_provider, query_value).unwrap(), &signer, ) .unwrap(); @@ -198,7 +221,9 @@ async fn partial_then_finalize_valid_receipt( #[rstest] #[tokio::test] async fn standard_lifetime_valid_receipt( - allocation_ids: Vec
, + payer: Address, + data_service: Address, + service_provider: Address, domain_separator: Eip712Domain, context: ContextFixture, ) { @@ -214,7 +239,7 @@ async fn standard_lifetime_valid_receipt( let query_value = 20u128; let signed_receipt = EIP712SignedMessage::new( &domain_separator, - Receipt::new(allocation_ids[0], query_value).unwrap(), + Receipt::new(payer, data_service, service_provider, query_value).unwrap(), &signer, ) .unwrap(); diff --git a/tap_core/tests/snapshots/rav_test__check_for_rav_serialization-2.snap b/tap_core/tests/snapshots/rav_test__check_for_rav_serialization-2.snap index 836c4c7c..d9ec3b3f 100644 --- a/tap_core/tests/snapshots/rav_test__check_for_rav_serialization-2.snap +++ b/tap_core/tests/snapshots/rav_test__check_for_rav_serialization-2.snap @@ -5,13 +5,16 @@ snapshot_kind: text --- { "message": { - "allocationId": "0xabababababababababababababababababababab", + "payer": "0xabababababababababababababababababababab", + "dataService": "0xabababababababababababababababababababab", + "serviceProvider": "0xabababababababababababababababababababab", "timestampNs": 59, - "valueAggregate": 545 + "valueAggregate": 545, + "metadata": "0x" }, "signature": { - "r": "0x11d760201bac73d4e772d0999a1f9b5f6b8d8979d94ee29b7cb2659d23f2a551", - "s": "0x1036a994ff414de83f24601ab7cc22e0ece134d2199e0b675d94bd8cf7015226", + "r": "0xe1a54286f4c8d483c410eb1d6a3972593d81b3f6d89458d9c177b4cd0aaf7fa9", + "s": "0x1307ee4fee865c2fad8e6373ad5873a54f614ecb4d8f60ead3641e6c1b959405", "yParity": "0x0", "v": "0x0" } diff --git a/tap_core/tests/snapshots/rav_test__check_for_rav_serialization.snap b/tap_core/tests/snapshots/rav_test__check_for_rav_serialization.snap index 2020b5b4..188e7087 100644 --- a/tap_core/tests/snapshots/rav_test__check_for_rav_serialization.snap +++ b/tap_core/tests/snapshots/rav_test__check_for_rav_serialization.snap @@ -6,142 +6,162 @@ snapshot_kind: text [ { "message": { - "allocation_id": "0xabababababababababababababababababababab", + "payer": "0xabababababababababababababababababababab", + "data_service": "0xabababababababababababababababababababab", + "service_provider": "0xabababababababababababababababababababab", "timestamp_ns": 50, "nonce": 50, "value": 50 }, "signature": { - "r": "0x5257bab234e33525cd999db4defc805c2d3b4e51cde3697f43e37ce39473720f", - "s": "0x6c3af14c3d400dfd047fd2da90eb9e8cee863e77cc52742ebcbf080b8d6ec2", + "r": "0x4ecb862a64112bcdac18567b9ecdea86bdaa23278363dd9ad7b0866460443cff", + "s": "0x55c351e35b610c372d988d9854701c4c539ca171f0daad0e2da391689cb9b739", "yParity": "0x1", "v": "0x1" } }, { "message": { - "allocation_id": "0xabababababababababababababababababababab", + "payer": "0xabababababababababababababababababababab", + "data_service": "0xabababababababababababababababababababab", + "service_provider": "0xabababababababababababababababababababab", "timestamp_ns": 51, "nonce": 51, "value": 51 }, "signature": { - "r": "0x1596dd0d380ede7aa5dec5ed09ea7d1fa8e4bc8dfdb43a4e965bb4f16906e321", - "s": "0x788b69625a031fbd2e769928b63505387df16e7c51f19ff67c782bfec101a387", + "r": "0xb86b4f2a3952fe0a63b853571f9ba3a8949d60fd47aa77b4079507b2e0d183a9", + "s": "0x6f0692e52df1a2162080ef8f471032b2d456fd64f193f0be42e461ad9be69f44", "yParity": "0x0", "v": "0x0" } }, { "message": { - "allocation_id": "0xabababababababababababababababababababab", + "payer": "0xabababababababababababababababababababab", + "data_service": "0xabababababababababababababababababababab", + "service_provider": "0xabababababababababababababababababababab", "timestamp_ns": 52, "nonce": 52, "value": 52 }, "signature": { - "r": "0xb3b8e2c1249fc14183024e28b14f7749ef852c898906c2442f380a26bf07a625", - "s": "0x6925e7dce01d539a658d552e43cfd92d9d204d6997604f8f613977251b964db3", - "yParity": "0x1", - "v": "0x1" + "r": "0xcc84e1950cf91c07596e9e8a7919a438f41598d2ad0b1d36bd4ca873387e3bf", + "s": "0x69ba08cbf960f893276193b2ceb285cd4597d681a841c9f09f36d56aee579edb", + "yParity": "0x0", + "v": "0x0" } }, { "message": { - "allocation_id": "0xabababababababababababababababababababab", + "payer": "0xabababababababababababababababababababab", + "data_service": "0xabababababababababababababababababababab", + "service_provider": "0xabababababababababababababababababababab", "timestamp_ns": 53, "nonce": 53, "value": 53 }, "signature": { - "r": "0x3b4d08db319497c2cc0d515d25057e28ce44b194a23e84b9d35682f97027c7e3", - "s": "0x232e02eb4b52d302d620867a4c10829e5a307404ea1bcbbd2ee33e8422a18a16", - "yParity": "0x1", - "v": "0x1" + "r": "0x9ea79f4be4c140a264e2d1a203cd7dd93d1495b25093783bb7fb18a2c22d0fe5", + "s": "0x39040040de42a251eae1c0a71e08d775416351f05199be7807400dce1d498afd", + "yParity": "0x0", + "v": "0x0" } }, { "message": { - "allocation_id": "0xabababababababababababababababababababab", + "payer": "0xabababababababababababababababababababab", + "data_service": "0xabababababababababababababababababababab", + "service_provider": "0xabababababababababababababababababababab", "timestamp_ns": 54, "nonce": 54, "value": 54 }, "signature": { - "r": "0x619d84f659ea3941cdb0656100b2ea8a3d2f5658dbd67f796ebfb8840156530b", - "s": "0x163b236f88207b89452255da8ce196997d8f2f0880081659c780f2093797f75e", - "yParity": "0x1", - "v": "0x1" + "r": "0x21f8af664178560f5aa274ea98ee145ce479d1295da4fed08c3d7102df8cc2af", + "s": "0x540418686c0f21d48786e46f773205d2b4ecaa5f0876cf6c8f4dff15d89d7510", + "yParity": "0x0", + "v": "0x0" } }, { "message": { - "allocation_id": "0xabababababababababababababababababababab", + "payer": "0xabababababababababababababababababababab", + "data_service": "0xabababababababababababababababababababab", + "service_provider": "0xabababababababababababababababababababab", "timestamp_ns": 55, "nonce": 55, "value": 55 }, "signature": { - "r": "0x48e1e0e31eaf40eabbcbc3c6d125b7656c0796d51188f89d27194e22f2c5d6bb", - "s": "0xd26efc0ae8cc3646993a20b5aabac1125ecb149ad91d733c702ac9f03222b66", + "r": "0x522915411cc85754f513d582c1d6fc38fa348a48eac0b8fddb3293ba87e41437", + "s": "0xde39cb8b91574ec392bc07367aea8df7d1cf37f9d2489ff6e5b4ea8b5ee50f2", "yParity": "0x1", "v": "0x1" } }, { "message": { - "allocation_id": "0xabababababababababababababababababababab", + "payer": "0xabababababababababababababababababababab", + "data_service": "0xabababababababababababababababababababab", + "service_provider": "0xabababababababababababababababababababab", "timestamp_ns": 56, "nonce": 56, "value": 56 }, "signature": { - "r": "0xc3adb8be5db130f563d3a18fc9e742fca84f69a903413e04dc567b9c3aca8626", - "s": "0x564dd73bdd33897c7a085e4eb1bc0ce002b1d65c6006781ab54cd670846fe358", - "yParity": "0x0", - "v": "0x0" + "r": "0x7b0199df25fc87969fcdf795e9cfd246e743d786a9208614b00d8af03730398", + "s": "0x772b54a7bc5da81d06534b8e524fa0e52019f76c826eead029c7903fcb19ea42", + "yParity": "0x1", + "v": "0x1" } }, { "message": { - "allocation_id": "0xabababababababababababababababababababab", + "payer": "0xabababababababababababababababababababab", + "data_service": "0xabababababababababababababababababababab", + "service_provider": "0xabababababababababababababababababababab", "timestamp_ns": 57, "nonce": 57, "value": 57 }, "signature": { - "r": "0xa0fe51e1b7253daed14f99c9320d0a539ef18b6ead6552947e5c93dde6f40dea", - "s": "0x4277d66d3a8c9f67cddc8d96a71ef8437e47e34a5b5789d7843eb691c3b9864", + "r": "0x72d7802e0802e8391469a9711259e6a9983ebab673d2baf7eceadfef9c2afc77", + "s": "0x647e0ae9f3ef205d31955b3ac3e132296b57b1b218cb5f221678ca7ab7e0b875", "yParity": "0x0", "v": "0x0" } }, { "message": { - "allocation_id": "0xabababababababababababababababababababab", + "payer": "0xabababababababababababababababababababab", + "data_service": "0xabababababababababababababababababababab", + "service_provider": "0xabababababababababababababababababababab", "timestamp_ns": 58, "nonce": 58, "value": 58 }, "signature": { - "r": "0x26f1657e4b8759867820be12c25e982e15ff9d70aa99fe1fd2587cbb644829de", - "s": "0x5cabbd965f93e544b07e5956c2831148dbf7960b4e2edadfa6ecbf1209dacda4", + "r": "0x98a01a0cad9ff3ab95157d03c6d253872935149f361fa3003b4776ea095b907e", + "s": "0x55034f5bdac601bd78a3091d82450e844a8ff1e554498fb0ef6b8c4ef9e61a6", "yParity": "0x0", "v": "0x0" } }, { "message": { - "allocation_id": "0xabababababababababababababababababababab", + "payer": "0xabababababababababababababababababababab", + "data_service": "0xabababababababababababababababababababab", + "service_provider": "0xabababababababababababababababababababab", "timestamp_ns": 59, "nonce": 59, "value": 59 }, "signature": { - "r": "0x90ce08049b9ce9fa38077ebeed0e24558442d8ae001aeff6b9f4b06f4f553c69", - "s": "0x7a873491448ae696555f9d1314b4e78a7cc98a19a6b0c26aad562053dc26a202", - "yParity": "0x1", - "v": "0x1" + "r": "0x27ce1976e8a0645d04e31f95c14b038f75de27e8fb1e4604b1ac7723232228cb", + "s": "0x31652a9a504057ca9c22d577370538d38b3c8a74070e3a844172e280f6587946", + "yParity": "0x0", + "v": "0x0" } } ] diff --git a/tap_integration_tests/tests/showcase.rs b/tap_integration_tests/tests/showcase.rs index 19210b34..5eb72c8c 100644 --- a/tap_integration_tests/tests/showcase.rs +++ b/tap_integration_tests/tests/showcase.rs @@ -219,6 +219,8 @@ fn requests_1( num_batches, &keys_sender, allocation_ids[0], + allocation_ids[0], + allocation_ids[0], &domain_separator, ) } @@ -237,6 +239,8 @@ fn requests_2( num_batches, &keys_sender, allocation_ids[1], + allocation_ids[1], + allocation_ids[1], &domain_separator, ) } @@ -256,6 +260,8 @@ fn repeated_timestamp_request( num_batches, &keys_sender, allocation_ids[0], + allocation_ids[0], + allocation_ids[0], &domain_separator, ); @@ -265,7 +271,9 @@ fn repeated_timestamp_request( .timestamp_ns; let target_receipt = &requests[receipt_threshold_1 as usize].message; let repeat_receipt = Receipt { - allocation_id: target_receipt.allocation_id, + payer: target_receipt.payer, + data_service: target_receipt.data_service, + service_provider: target_receipt.service_provider, timestamp_ns: repeat_timestamp, nonce: target_receipt.nonce, value: target_receipt.value, @@ -292,6 +300,8 @@ fn repeated_timestamp_incremented_by_one_request( num_batches, &keys_sender, allocation_ids[0], + allocation_ids[0], + allocation_ids[0], &domain_separator, ); @@ -302,7 +312,9 @@ fn repeated_timestamp_incremented_by_one_request( + 1; let target_receipt = &requests[receipt_threshold_1 as usize].message; let repeat_receipt = Receipt { - allocation_id: target_receipt.allocation_id, + payer: target_receipt.payer, + data_service: target_receipt.data_service, + service_provider: target_receipt.service_provider, timestamp_ns: repeat_timestamp, nonce: target_receipt.nonce, value: target_receipt.value, @@ -330,6 +342,8 @@ fn wrong_requests( num_batches, &wrong_keys_sender, allocation_ids[0], + allocation_ids[0], + allocation_ids[0], &domain_separator, ) } @@ -773,7 +787,9 @@ fn generate_requests( query_price: &[u128], num_batches: u64, sender_key: &PrivateKeySigner, - allocation_id: Address, + payer: Address, + data_service: Address, + service_provider: Address, domain_separator: &Eip712Domain, ) -> Vec> { let mut requests: Vec> = Vec::new(); @@ -783,7 +799,7 @@ fn generate_requests( requests.push( EIP712SignedMessage::new( domain_separator, - Receipt::new(allocation_id, *value).unwrap(), + Receipt::new(payer, data_service, service_provider, *value).unwrap(), sender_key, ) .unwrap(),