From 8758bea17cdbd759ed4f5934f9bd6eb604b2fe3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Mon, 14 Oct 2024 11:39:12 +0200 Subject: [PATCH] Use ticket type when retrieving from storage (#4947) --- Cargo.lock | 1 + common/bandwidth-controller/src/lib.rs | 12 ++++++++---- common/client-libs/gateway-client/Cargo.toml | 1 + common/client-libs/gateway-client/src/client/mod.rs | 7 ++++++- common/commands/src/ecash/generate_ticket.rs | 7 ++++++- common/commands/src/ecash/issue_ticket_book.rs | 2 +- common/credential-storage/src/backends/memory.rs | 2 ++ common/credential-storage/src/backends/sqlite.rs | 3 +++ common/credential-storage/src/ephemeral_storage.rs | 5 +++-- .../credential-storage/src/persistent_storage/mod.rs | 5 ++++- common/credential-storage/src/storage.rs | 3 ++- 11 files changed, 37 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2e74311fa1..a35a6acaaf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5251,6 +5251,7 @@ dependencies = [ "nym-bandwidth-controller", "nym-credential-storage", "nym-credentials", + "nym-credentials-interface", "nym-crypto", "nym-gateway-requests", "nym-network-defaults", diff --git a/common/bandwidth-controller/src/lib.rs b/common/bandwidth-controller/src/lib.rs index a164d3df60..a9b15db1fb 100644 --- a/common/bandwidth-controller/src/lib.rs +++ b/common/bandwidth-controller/src/lib.rs @@ -16,7 +16,7 @@ use nym_credential_storage::models::RetrievedTicketbook; use nym_credential_storage::storage::Storage; use nym_credentials::ecash::bandwidth::CredentialSpendingData; use nym_credentials_interface::{ - AnnotatedCoinIndexSignature, AnnotatedExpirationDateSignature, VerificationKeyAuth, + AnnotatedCoinIndexSignature, AnnotatedExpirationDateSignature, TicketType, VerificationKeyAuth, }; use nym_ecash_time::Date; use nym_validator_client::nym_api::EpochId; @@ -64,9 +64,10 @@ impl BandwidthController { BandwidthController { storage, client } } - /// Tries to retrieve one of the stored, unused credentials that hasn't yet expired. + /// Tries to retrieve one of the stored, unused credentials for the given type that hasn't yet expired. pub async fn get_next_usable_ticketbook( &self, + ticketbook_type: TicketType, tickets: u32, ) -> Result where @@ -74,7 +75,7 @@ impl BandwidthController { { let Some(ticketbook) = self .storage - .get_next_unspent_usable_ticketbook(tickets) + .get_next_unspent_usable_ticketbook(ticketbook_type.to_string(), tickets) .await .map_err(BandwidthControllerError::credential_storage_error)? else { @@ -181,6 +182,7 @@ impl BandwidthController { pub async fn prepare_ecash_ticket( &self, + ticketbook_type: TicketType, provider_pk: [u8; 32], tickets_to_spend: u32, ) -> Result @@ -188,7 +190,9 @@ impl BandwidthController { C: DkgQueryClient + Sync + Send, ::StorageError: Send + Sync + 'static, { - let retrieved_ticketbook = self.get_next_usable_ticketbook(tickets_to_spend).await?; + let retrieved_ticketbook = self + .get_next_usable_ticketbook(ticketbook_type, tickets_to_spend) + .await?; let ticketbook_id = retrieved_ticketbook.ticketbook_id; let epoch_id = retrieved_ticketbook.ticketbook.epoch_id(); diff --git a/common/client-libs/gateway-client/Cargo.toml b/common/client-libs/gateway-client/Cargo.toml index 418debb4a9..81b9b4d7f4 100644 --- a/common/client-libs/gateway-client/Cargo.toml +++ b/common/client-libs/gateway-client/Cargo.toml @@ -24,6 +24,7 @@ zeroize.workspace = true nym-bandwidth-controller = { path = "../../bandwidth-controller" } nym-credentials = { path = "../../credentials" } nym-credential-storage = { path = "../../credential-storage" } +nym-credentials-interface = { path = "../../credentials-interface" } nym-crypto = { path = "../../crypto" } nym-gateway-requests = { path = "../../gateway-requests" } nym-network-defaults = { path = "../../network-defaults" } diff --git a/common/client-libs/gateway-client/src/client/mod.rs b/common/client-libs/gateway-client/src/client/mod.rs index 2278c6fa47..58e061887e 100644 --- a/common/client-libs/gateway-client/src/client/mod.rs +++ b/common/client-libs/gateway-client/src/client/mod.rs @@ -16,6 +16,7 @@ use nym_bandwidth_controller::{BandwidthController, BandwidthStatusMessage}; use nym_credential_storage::ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage; use nym_credential_storage::storage::Storage as CredentialStorage; use nym_credentials::CredentialSpendingData; +use nym_credentials_interface::TicketType; use nym_crypto::asymmetric::identity; use nym_gateway_requests::registration::handshake::client_handshake; use nym_gateway_requests::{ @@ -748,7 +749,11 @@ impl GatewayClient { } let prepared_credential = self .unchecked_bandwidth_controller() - .prepare_ecash_ticket(self.gateway_identity.to_bytes(), TICKETS_TO_SPEND) + .prepare_ecash_ticket( + TicketType::V1MixnetEntry, + self.gateway_identity.to_bytes(), + TICKETS_TO_SPEND, + ) .await?; match self.claim_ecash_bandwidth(prepared_credential.data).await { diff --git a/common/commands/src/ecash/generate_ticket.rs b/common/commands/src/ecash/generate_ticket.rs index 67a85ab093..0da2a878c4 100644 --- a/common/commands/src/ecash/generate_ticket.rs +++ b/common/commands/src/ecash/generate_ticket.rs @@ -9,10 +9,15 @@ use comfy_table::Table; use nym_credential_storage::initialise_persistent_storage; use nym_credential_storage::storage::Storage; use nym_credentials::ecash::bandwidth::serialiser::VersionedSerialise; +use nym_credentials_interface::TicketType; use std::path::PathBuf; #[derive(Debug, Parser)] pub struct Args { + /// Specify which type of ticketbook + #[clap(long, default_value_t = TicketType::V1MixnetEntry)] + pub(crate) ticketbook_type: TicketType, + /// Specify the index of the ticket to retrieve from the ticketbook. /// By default, the current unspent value is used. #[clap(long, group = "output")] @@ -62,7 +67,7 @@ pub async fn execute(args: Args) -> anyhow::Result<()> { let persistent_storage = initialise_persistent_storage(&credentials_store).await; let Some(mut next_ticketbook) = persistent_storage - .get_next_unspent_usable_ticketbook(0) + .get_next_unspent_usable_ticketbook(args.ticketbook_type.to_string(), 0) .await? else { bail!( diff --git a/common/commands/src/ecash/issue_ticket_book.rs b/common/commands/src/ecash/issue_ticket_book.rs index 28e8c3eafc..0097f4676a 100644 --- a/common/commands/src/ecash/issue_ticket_book.rs +++ b/common/commands/src/ecash/issue_ticket_book.rs @@ -107,7 +107,7 @@ async fn issue_to_file(args: Args, client: SigningClient) -> anyhow::Result<()> utils::issue_credential(&client, &credentials_store, &secret, args.ticketbook_type).await?; let ticketbook = credentials_store - .get_next_unspent_usable_ticketbook(0) + .get_next_unspent_usable_ticketbook(args.ticketbook_type.to_string(), 0) .await? .ok_or(anyhow!("we just issued a ticketbook, it must be present!"))? .ticketbook; diff --git a/common/credential-storage/src/backends/memory.rs b/common/credential-storage/src/backends/memory.rs index d107677897..91d197d632 100644 --- a/common/credential-storage/src/backends/memory.rs +++ b/common/credential-storage/src/backends/memory.rs @@ -73,6 +73,7 @@ impl MemoryEcachTicketbookManager { pub async fn get_next_unspent_ticketbook_and_update( &self, + ticketbook_type: String, tickets: u32, ) -> Option { let mut guard = self.inner.write().await; @@ -81,6 +82,7 @@ impl MemoryEcachTicketbookManager { if !t.ticketbook.expired() && t.ticketbook.spent_tickets() + tickets as u64 <= t.ticketbook.params_total_tickets() + && t.ticketbook.ticketbook_type().to_string() == ticketbook_type { t.ticketbook .update_spent_tickets(t.ticketbook.spent_tickets() + tickets as u64); diff --git a/common/credential-storage/src/backends/sqlite.rs b/common/credential-storage/src/backends/sqlite.rs index 8c5b20c7d8..9267bbddb3 100644 --- a/common/credential-storage/src/backends/sqlite.rs +++ b/common/credential-storage/src/backends/sqlite.rs @@ -284,6 +284,7 @@ impl SqliteEcashTicketbookManager { pub(crate) async fn get_next_unspent_ticketbook<'a, E>( executor: E, + ticketbook_type: String, deadline: Date, tickets: u32, ) -> Result, sqlx::Error> @@ -296,12 +297,14 @@ where FROM ecash_ticketbook WHERE used_tickets + ? <= total_tickets AND expiration_date >= ? + AND ticketbook_type = ? ORDER BY expiration_date ASC LIMIT 1 "#, ) .bind(tickets) .bind(deadline) + .bind(ticketbook_type) .fetch_optional(executor) .await } diff --git a/common/credential-storage/src/ephemeral_storage.rs b/common/credential-storage/src/ephemeral_storage.rs index 4b3ef93660..91436d4d8c 100644 --- a/common/credential-storage/src/ephemeral_storage.rs +++ b/common/credential-storage/src/ephemeral_storage.rs @@ -85,17 +85,18 @@ impl Storage for EphemeralStorage { Ok(()) } - /// Tries to retrieve one of the stored ticketbook, + /// Tries to retrieve one of the stored ticketbook for the specified type, /// that has not yet expired and has required number of unspent tickets. /// it immediately updated the on-disk number of used tickets so that another task /// could obtain their own tickets at the same time async fn get_next_unspent_usable_ticketbook( &self, + ticketbook_type: String, tickets: u32, ) -> Result, Self::StorageError> { Ok(self .storage_manager - .get_next_unspent_ticketbook_and_update(tickets) + .get_next_unspent_ticketbook_and_update(ticketbook_type, tickets) .await) } diff --git a/common/credential-storage/src/persistent_storage/mod.rs b/common/credential-storage/src/persistent_storage/mod.rs index c5daceabd5..8f5cf7610d 100644 --- a/common/credential-storage/src/persistent_storage/mod.rs +++ b/common/credential-storage/src/persistent_storage/mod.rs @@ -171,13 +171,16 @@ impl Storage for PersistentStorage { /// could obtain their own tickets at the same time async fn get_next_unspent_usable_ticketbook( &self, + ticketbook_type: String, tickets: u32, ) -> Result, Self::StorageError> { let deadline = ecash_today().ecash_date(); let mut tx = self.storage_manager.begin_storage_tx().await?; // we don't want ticketbooks with expiration in the past - let Some(raw) = get_next_unspent_ticketbook(&mut tx, deadline, tickets).await? else { + let Some(raw) = + get_next_unspent_ticketbook(&mut tx, ticketbook_type, deadline, tickets).await? + else { // make sure to finish our tx tx.commit().await?; return Ok(None); diff --git a/common/credential-storage/src/storage.rs b/common/credential-storage/src/storage.rs index 7033cd6e1f..19ddc44e86 100644 --- a/common/credential-storage/src/storage.rs +++ b/common/credential-storage/src/storage.rs @@ -45,12 +45,13 @@ pub trait Storage: Send + Sync { async fn remove_pending_ticketbook(&self, pending_id: i64) -> Result<(), Self::StorageError>; - /// Tries to retrieve one of the stored ticketbook, + /// Tries to retrieve one of the stored ticketbook for the specified type, /// that has not yet expired and has required number of unspent tickets. /// it immediately updated the on-disk number of used tickets so that another task /// could obtain their own tickets at the same time async fn get_next_unspent_usable_ticketbook( &self, + ticketbook_type: String, tickets: u32, ) -> Result, Self::StorageError>;