Skip to content

Commit

Permalink
Merge pull request #577 from thesimplekid/fix_mint_delete_unspent
Browse files Browse the repository at this point in the history
Fix mint delete unspent
  • Loading branch information
thesimplekid authored Feb 5, 2025
2 parents 3a267d5 + a168121 commit 609840a
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 20 deletions.
8 changes: 7 additions & 1 deletion crates/cdk-common/src/database/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,14 @@ pub trait Database {
/// Get [`MintKeySetInfo`]s
async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err>;

/// Add spent [`Proofs`]
/// Add [`Proofs`]
async fn add_proofs(&self, proof: Proofs, quote_id: Option<Uuid>) -> Result<(), Self::Err>;
/// Remove [`Proofs`]
async fn remove_proofs(
&self,
ys: &[PublicKey],
quote_id: Option<Uuid>,
) -> Result<(), Self::Err>;
/// Get [`Proofs`] by ys
async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result<Vec<Option<Proof>>, Self::Err>;
/// Get ys by quote id
Expand Down
41 changes: 41 additions & 0 deletions crates/cdk-redb/src/mint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,47 @@ impl MintDatabase for MintRedbDatabase {
Ok(())
}

async fn remove_proofs(
&self,
ys: &[PublicKey],
quote_id: Option<Uuid>,
) -> Result<(), Self::Err> {
let write_txn = self.db.begin_write().map_err(Error::from)?;

{
let mut proofs_table = write_txn.open_table(PROOFS_TABLE).map_err(Error::from)?;

for y in ys {
proofs_table.remove(&y.to_bytes()).map_err(Error::from)?;
}
}

{
let mut proof_state_table = write_txn
.open_table(PROOFS_STATE_TABLE)
.map_err(Error::from)?;
for y in ys {
proof_state_table
.remove(&y.to_bytes())
.map_err(Error::from)?;
}
}

if let Some(quote_id) = quote_id {
let mut quote_proofs_table = write_txn
.open_multimap_table(QUOTE_PROOFS_TABLE)
.map_err(Error::from)?;

quote_proofs_table
.remove_all(quote_id.as_bytes())
.map_err(Error::from)?;
}

write_txn.commit().map_err(Error::from)?;

Ok(())
}

async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result<Vec<Option<Proof>>, Self::Err> {
let read_txn = self.db.begin_read().map_err(Error::from)?;
let table = read_txn.open_table(PROOFS_TABLE).map_err(Error::from)?;
Expand Down
27 changes: 27 additions & 0 deletions crates/cdk-sqlite/src/mint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,33 @@ VALUES (?, ?, ?, ?, ?, ?, ?, ?);
Ok(())
}

async fn remove_proofs(
&self,
ys: &[PublicKey],
_quote_id: Option<Uuid>,
) -> Result<(), Self::Err> {
let mut transaction = self.pool.begin().await.map_err(Error::from)?;

let sql = format!(
"DELETE FROM proof WHERE y IN ({})",
std::iter::repeat("?")
.take(ys.len())
.collect::<Vec<_>>()
.join(",")
);

ys.iter()
.fold(sqlx::query(&sql), |query, y| {
query.bind(y.to_bytes().to_vec())
})
.execute(&mut transaction)
.await
.map_err(Error::from)?;

transaction.commit().await.map_err(Error::from)?;
Ok(())
}

async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result<Vec<Option<Proof>>, Self::Err> {
let mut transaction = self.pool.begin().await.map_err(Error::from)?;

Expand Down
29 changes: 29 additions & 0 deletions crates/cdk/src/cdk_database/mint_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,35 @@ impl MintDatabase for MintMemoryDatabase {
Ok(())
}

async fn remove_proofs(
&self,
ys: &[PublicKey],
quote_id: Option<Uuid>,
) -> Result<(), Self::Err> {
{
let mut db_proofs = self.proofs.write().await;

ys.iter().for_each(|y| {
db_proofs.remove(&y.to_bytes());
});
}

{
let mut db_proofs_state = self.proof_state.lock().await;

ys.iter().for_each(|y| {
db_proofs_state.remove(&y.to_bytes());
});
}

if let Some(quote_id) = quote_id {
let mut quote_proofs = self.quote_proofs.lock().await;
quote_proofs.remove(&quote_id);
}

Ok(())
}

async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result<Vec<Option<Proof>>, Self::Err> {
let spent_proofs = self.proofs.read().await;

Expand Down
2 changes: 1 addition & 1 deletion crates/cdk/src/mint/melt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ impl Mint {
let input_ys = melt_request.inputs.ys()?;

self.localstore
.update_proofs_states(&input_ys, State::Unspent)
.remove_proofs(&input_ys, Some(melt_request.quote))
.await?;

self.localstore
Expand Down
24 changes: 6 additions & 18 deletions crates/cdk/src/mint/swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,14 @@ impl Mint {
.len()
.ne(&proof_count)
{
self.localstore
.update_proofs_states(&input_ys, State::Unspent)
.await?;
self.localstore.remove_proofs(&input_ys, None).await?;
return Err(Error::DuplicateProofs);
}

for proof in &swap_request.inputs {
if let Err(err) = self.verify_proof(proof).await {
tracing::info!("Error verifying proof in swap");
self.localstore
.update_proofs_states(&input_ys, State::Unspent)
.await?;
self.localstore.remove_proofs(&input_ys, None).await?;
return Err(err);
}
}
Expand All @@ -100,9 +96,7 @@ impl Mint {
}
None => {
tracing::info!("Swap request with unknown keyset in inputs");
self.localstore
.update_proofs_states(&input_ys, State::Unspent)
.await?;
self.localstore.remove_proofs(&input_ys, None).await?;
}
}
}
Expand All @@ -117,9 +111,7 @@ impl Mint {
}
None => {
tracing::info!("Swap request with unknown keyset in outputs");
self.localstore
.update_proofs_states(&input_ys, State::Unspent)
.await?;
self.localstore.remove_proofs(&input_ys, None).await?;
}
}
}
Expand All @@ -129,9 +121,7 @@ impl Mint {
// now
if keyset_units.len().gt(&1) {
tracing::error!("Only one unit is allowed in request: {:?}", keyset_units);
self.localstore
.update_proofs_states(&input_ys, State::Unspent)
.await?;
self.localstore.remove_proofs(&input_ys, None).await?;
return Err(Error::UnsupportedUnit);
}

Expand All @@ -146,9 +136,7 @@ impl Mint {
for blinded_message in &swap_request.outputs {
if let Err(err) = blinded_message.verify_p2pk(&pubkeys, sigs_required) {
tracing::info!("Could not verify p2pk in swap request");
self.localstore
.update_proofs_states(&input_ys, State::Unspent)
.await?;
self.localstore.remove_proofs(&input_ys, None).await?;
return Err(err.into());
}
}
Expand Down

0 comments on commit 609840a

Please sign in to comment.