bugfix: make sure to update timestamp of last batch verification to prevent double redemption (#5239)
This commit is contained in:
committed by
GitHub
parent
c29fce0856
commit
66fea38d20
Generated
+1
-1
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
}))
|
||||
|
||||
@@ -890,7 +890,7 @@ impl EcashState {
|
||||
|
||||
pub async fn get_redeemable_tickets(
|
||||
&self,
|
||||
provider_info: TicketProvider,
|
||||
provider_info: &TicketProvider,
|
||||
) -> Result<Vec<SerialNumberWrapper>> {
|
||||
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],
|
||||
|
||||
@@ -82,6 +82,11 @@ pub trait EcashStorageManagerExt {
|
||||
provider_id: i64,
|
||||
since: OffsetDateTime,
|
||||
) -> Result<Vec<SerialNumberWrapper>, 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(())
|
||||
}
|
||||
|
||||
|
||||
@@ -112,6 +112,11 @@ pub trait EcashStorageExt {
|
||||
provider_id: i64,
|
||||
since: OffsetDateTime,
|
||||
) -> Result<Vec<SerialNumberWrapper>, 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,
|
||||
|
||||
Reference in New Issue
Block a user