diff --git a/Cargo.lock b/Cargo.lock index f194e4e0f6..f3585f8d7e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6058,7 +6058,7 @@ dependencies = [ [[package]] name = "nym-node-status-api" -version = "1.0.0-rc.6" +version = "1.0.0-rc.7" dependencies = [ "anyhow", "axum 0.7.7", diff --git a/nym-api/src/ecash/api_routes/spending.rs b/nym-api/src/ecash/api_routes/spending.rs index 3bda629174..f52aeda2eb 100644 --- a/nym-api/src/ecash/api_routes/spending.rs +++ b/nym-api/src/ecash/api_routes/spending.rs @@ -203,7 +203,7 @@ async fn batch_redeem_tickets( // 5. check if **every** serial number included in the request has been verified by us // if we have more than requested, tough luck, they're going to lose them - let verified = state.get_redeemable_tickets(provider_info).await?; + let verified = state.get_redeemable_tickets(&provider_info).await?; let verified_tickets: HashSet<_> = verified.iter().map(|sn| sn.deref()).collect(); for sn in &received { @@ -215,8 +215,14 @@ async fn batch_redeem_tickets( } } + // 6. vote on the proposal // TODO: offload it to separate task with work queue and batching (of tx messages) to vote for multiple proposals in the same tx + // similarly to what we do inside the credential proxy state.accept_proposal(proposal_id).await?; + + // 7. update the time of the last verification for this provider + state.update_last_batch_verification(&provider_info).await?; + Ok(Json(EcashBatchTicketRedemptionResponse { proposal_accepted: true, })) diff --git a/nym-api/src/ecash/state/mod.rs b/nym-api/src/ecash/state/mod.rs index f262177480..3e716d08f4 100644 --- a/nym-api/src/ecash/state/mod.rs +++ b/nym-api/src/ecash/state/mod.rs @@ -890,7 +890,7 @@ impl EcashState { pub async fn get_redeemable_tickets( &self, - provider_info: TicketProvider, + provider_info: &TicketProvider, ) -> Result> { let since = provider_info .last_batch_verification @@ -903,6 +903,14 @@ impl EcashState { .map_err(Into::into) } + pub async fn update_last_batch_verification(&self, provider: &TicketProvider) -> Result<()> { + Ok(self + .aux + .storage + .update_last_batch_verification(provider.id, OffsetDateTime::now_utc()) + .await?) + } + pub async fn get_ticket_data_by_serial_number( &self, serial_number: &[u8], diff --git a/nym-api/src/ecash/storage/manager.rs b/nym-api/src/ecash/storage/manager.rs index f3b227b5b0..7e49215c70 100644 --- a/nym-api/src/ecash/storage/manager.rs +++ b/nym-api/src/ecash/storage/manager.rs @@ -82,6 +82,11 @@ pub trait EcashStorageManagerExt { provider_id: i64, since: OffsetDateTime, ) -> Result, sqlx::Error>; + async fn update_last_batch_verification( + &self, + provider_id: i64, + last_batch_verification: OffsetDateTime, + ) -> Result<(), sqlx::Error>; async fn get_spent_tickets_on( &self, @@ -215,15 +220,15 @@ impl EcashStorageManagerExt for StorageManager { "#, expiration_date ) - .fetch_all(&self.connection_pool) - .await? - .into_iter() - .filter_map(|r| r.merkle_leaf.try_into().inspect_err(|_| error!("possible database corruption: one of the stored merkle leaves is not a valid 32byte hash")).ok().map(|merkle_leaf| IssuedHash { - deposit_id: r.deposit_id, - merkle_leaf, - merkle_index: r.merkle_index as usize, - })) - .collect()) + .fetch_all(&self.connection_pool) + .await? + .into_iter() + .filter_map(|r| r.merkle_leaf.try_into().inspect_err(|_| error!("possible database corruption: one of the stored merkle leaves is not a valid 32byte hash")).ok().map(|merkle_leaf| IssuedHash { + deposit_id: r.deposit_id, + merkle_leaf, + merkle_index: r.merkle_index as usize, + })) + .collect()) } /// Store the provided issued credential information. @@ -344,8 +349,8 @@ impl EcashStorageManagerExt for StorageManager { verified_at, provider_id ) - .execute(&self.connection_pool) - .await?; + .execute(&self.connection_pool) + .await?; Ok(()) } @@ -382,6 +387,25 @@ impl EcashStorageManagerExt for StorageManager { .await } + async fn update_last_batch_verification( + &self, + provider_id: i64, + last_batch_verification: OffsetDateTime, + ) -> Result<(), sqlx::Error> { + sqlx::query!( + r#" + UPDATE ticket_providers + SET last_batch_verification = ? + WHERE id = ? + "#, + last_batch_verification, + provider_id + ) + .execute(&self.connection_pool) + .await?; + Ok(()) + } + async fn get_spent_tickets_on( &self, date: Date, @@ -510,8 +534,8 @@ impl EcashStorageManagerExt for StorageManager { epoch_id, data ) - .execute(&self.connection_pool) - .await?; + .execute(&self.connection_pool) + .await?; Ok(()) } @@ -544,8 +568,8 @@ impl EcashStorageManagerExt for StorageManager { epoch_id, data ) - .execute(&self.connection_pool) - .await?; + .execute(&self.connection_pool) + .await?; Ok(()) } diff --git a/nym-api/src/ecash/storage/mod.rs b/nym-api/src/ecash/storage/mod.rs index 019ab43a72..2d0d802f06 100644 --- a/nym-api/src/ecash/storage/mod.rs +++ b/nym-api/src/ecash/storage/mod.rs @@ -112,6 +112,11 @@ pub trait EcashStorageExt { provider_id: i64, since: OffsetDateTime, ) -> Result, NymApiStorageError>; + async fn update_last_batch_verification( + &self, + provider_id: i64, + last_batch_verification: OffsetDateTime, + ) -> Result<(), NymApiStorageError>; async fn get_all_spent_tickets_on( &self, @@ -395,6 +400,17 @@ impl EcashStorageExt for NymApiStorage { .map_err(Into::into) } + async fn update_last_batch_verification( + &self, + provider_id: i64, + last_batch_verification: OffsetDateTime, + ) -> Result<(), NymApiStorageError> { + Ok(self + .manager + .update_last_batch_verification(provider_id, last_batch_verification) + .await?) + } + async fn get_all_spent_tickets_on( &self, date: Date,