Sfoglia il codice sorgente

feat: add and remove proofs use vecs

thesimplekid 8 mesi fa
parent
commit
b0bfaec94a

+ 24 - 18
crates/cdk-redb/src/mint/mod.rs

@@ -453,7 +453,7 @@ impl MintDatabase for MintRedbDatabase {
         Ok(())
     }
 
-    async fn add_spent_proof(&self, proof: Proof) -> Result<(), Self::Err> {
+    async fn add_spent_proofs(&self, proofs: Vec<Proof>) -> Result<(), Self::Err> {
         let db = self.db.lock().await;
 
         let write_txn = db.begin_write().map_err(Error::from)?;
@@ -462,13 +462,15 @@ impl MintDatabase for MintRedbDatabase {
             let mut table = write_txn
                 .open_table(SPENT_PROOFS_TABLE)
                 .map_err(Error::from)?;
-            let y: PublicKey = hash_to_curve(&proof.secret.to_bytes()).map_err(Error::from)?;
-            table
-                .insert(
-                    y.to_bytes(),
-                    serde_json::to_string(&proof).map_err(Error::from)?.as_str(),
-                )
-                .map_err(Error::from)?;
+            for proof in proofs {
+                let y: PublicKey = hash_to_curve(&proof.secret.to_bytes()).map_err(Error::from)?;
+                table
+                    .insert(
+                        y.to_bytes(),
+                        serde_json::to_string(&proof).map_err(Error::from)?.as_str(),
+                    )
+                    .map_err(Error::from)?;
+            }
         }
         write_txn.commit().map_err(Error::from)?;
 
@@ -503,7 +505,7 @@ impl MintDatabase for MintRedbDatabase {
         }
     }
 
-    async fn add_pending_proof(&self, proof: Proof) -> Result<(), Self::Err> {
+    async fn add_pending_proofs(&self, proofs: Vec<Proof>) -> Result<(), Self::Err> {
         let db = self.db.lock().await;
 
         let write_txn = db.begin_write().map_err(Error::from)?;
@@ -512,12 +514,14 @@ impl MintDatabase for MintRedbDatabase {
             let mut table = write_txn
                 .open_table(PENDING_PROOFS_TABLE)
                 .map_err(Error::from)?;
-            table
-                .insert(
-                    hash_to_curve(&proof.secret.to_bytes())?.to_bytes(),
-                    serde_json::to_string(&proof).map_err(Error::from)?.as_str(),
-                )
-                .map_err(Error::from)?;
+            for proof in proofs {
+                table
+                    .insert(
+                        hash_to_curve(&proof.secret.to_bytes())?.to_bytes(),
+                        serde_json::to_string(&proof).map_err(Error::from)?.as_str(),
+                    )
+                    .map_err(Error::from)?;
+            }
         }
         write_txn.commit().map_err(Error::from)?;
 
@@ -555,7 +559,7 @@ impl MintDatabase for MintRedbDatabase {
         }
     }
 
-    async fn remove_pending_proof(&self, secret: &Secret) -> Result<(), Self::Err> {
+    async fn remove_pending_proofs(&self, secrets: Vec<&Secret>) -> Result<(), Self::Err> {
         let db = self.db.lock().await;
 
         let write_txn = db.begin_write().map_err(Error::from)?;
@@ -564,8 +568,10 @@ impl MintDatabase for MintRedbDatabase {
             let mut table = write_txn
                 .open_table(PENDING_PROOFS_TABLE)
                 .map_err(Error::from)?;
-            let secret_hash = hash_to_curve(&secret.to_bytes()).map_err(Error::from)?;
-            table.remove(secret_hash.to_bytes()).map_err(Error::from)?;
+            for secret in secrets {
+                let secret_hash = hash_to_curve(&secret.to_bytes()).map_err(Error::from)?;
+                table.remove(secret_hash.to_bytes()).map_err(Error::from)?;
+            }
         }
         write_txn.commit().map_err(Error::from)?;
 

+ 50 - 38
crates/cdk-sqlite/src/mint/mod.rs

@@ -10,7 +10,7 @@ use cdk::cdk_database::{self, MintDatabase};
 use cdk::mint::MintKeySetInfo;
 use cdk::nuts::nut05::QuoteState;
 use cdk::nuts::{
-    BlindSignature, CurrencyUnit, Id, MeltQuoteState, MintQuoteState, Proof, PublicKey,
+    BlindSignature, CurrencyUnit, Id, MeltQuoteState, MintQuoteState, Proof, Proofs, PublicKey,
 };
 use cdk::secret::Secret;
 use cdk::types::{MeltQuote, MintQuote};
@@ -405,25 +405,29 @@ FROM keyset;
             .collect())
     }
 
-    async fn add_spent_proof(&self, proof: Proof) -> Result<(), Self::Err> {
-        sqlx::query(
-            r#"
+    async fn add_spent_proofs(&self, proofs: Proofs) -> Result<(), Self::Err> {
+        let mut transaction = self.pool.begin().await.map_err(Error::from)?;
+
+        for proof in proofs {
+            sqlx::query(
+                r#"
 INSERT OR REPLACE INTO proof
 (y, amount, keyset_id, secret, c, witness, state)
 VALUES (?, ?, ?, ?, ?, ?, ?);
         "#,
-        )
-        .bind(proof.y()?.to_bytes().to_vec())
-        .bind(u64::from(proof.amount) as i64)
-        .bind(proof.keyset_id.to_string())
-        .bind(proof.secret.to_string())
-        .bind(proof.c.to_bytes().to_vec())
-        .bind(proof.witness.map(|w| serde_json::to_string(&w).unwrap()))
-        .bind("SPENT")
-        .execute(&self.pool)
-        .await
-        .map_err(Error::from)?;
-
+            )
+            .bind(proof.y()?.to_bytes().to_vec())
+            .bind(u64::from(proof.amount) as i64)
+            .bind(proof.keyset_id.to_string())
+            .bind(proof.secret.to_string())
+            .bind(proof.c.to_bytes().to_vec())
+            .bind(proof.witness.map(|w| serde_json::to_string(&w).unwrap()))
+            .bind("SPENT")
+            .execute(&mut transaction)
+            .await
+            .map_err(Error::from)?;
+        }
+        transaction.commit().await.map_err(Error::from)?;
         Ok(())
     }
     async fn get_spent_proof_by_secret(&self, secret: &Secret) -> Result<Option<Proof>, Self::Err> {
@@ -473,24 +477,28 @@ AND state="SPENT";
         Ok(Some(sqlite_row_to_proof(rec)?))
     }
 
-    async fn add_pending_proof(&self, proof: Proof) -> Result<(), Self::Err> {
-        sqlx::query(
-            r#"
+    async fn add_pending_proofs(&self, proofs: Proofs) -> Result<(), Self::Err> {
+        let mut transaction = self.pool.begin().await.map_err(Error::from)?;
+        for proof in proofs {
+            sqlx::query(
+                r#"
 INSERT OR REPLACE INTO proof
 (y, amount, keyset_id, secret, c, witness, spent, pending)
 VALUES (?, ?, ?, ?, ?, ?, ?);
         "#,
-        )
-        .bind(proof.y()?.to_bytes().to_vec())
-        .bind(u64::from(proof.amount) as i64)
-        .bind(proof.keyset_id.to_string())
-        .bind(proof.secret.to_string())
-        .bind(proof.c.to_bytes().to_vec())
-        .bind(proof.witness.map(|w| serde_json::to_string(&w).unwrap()))
-        .bind("PENDING")
-        .execute(&self.pool)
-        .await
-        .map_err(Error::from)?;
+            )
+            .bind(proof.y()?.to_bytes().to_vec())
+            .bind(u64::from(proof.amount) as i64)
+            .bind(proof.keyset_id.to_string())
+            .bind(proof.secret.to_string())
+            .bind(proof.c.to_bytes().to_vec())
+            .bind(proof.witness.map(|w| serde_json::to_string(&w).unwrap()))
+            .bind("PENDING")
+            .execute(&mut transaction)
+            .await
+            .map_err(Error::from)?;
+        }
+        transaction.commit().await.map_err(Error::from)?;
 
         Ok(())
     }
@@ -542,18 +550,22 @@ AND state="PENDING";
         };
         Ok(Some(sqlite_row_to_proof(rec)?))
     }
-    async fn remove_pending_proof(&self, secret: &Secret) -> Result<(), Self::Err> {
-        sqlx::query(
-            r#"
+    async fn remove_pending_proofs(&self, secrets: Vec<&Secret>) -> Result<(), Self::Err> {
+        let mut transaction = self.pool.begin().await.map_err(Error::from)?;
+        for secret in secrets {
+            sqlx::query(
+                r#"
 DELETE FROM proof
 WHERE secret=?
 AND state="PENDING";
         "#,
-        )
-        .bind(secret.to_string())
-        .execute(&self.pool)
-        .await
-        .map_err(Error::from)?;
+            )
+            .bind(secret.to_string())
+            .execute(&mut transaction)
+            .await
+            .map_err(Error::from)?;
+        }
+        transaction.commit().await.map_err(Error::from)?;
 
         Ok(())
     }

+ 21 - 17
crates/cdk/src/cdk_database/mint_memory.rs

@@ -179,12 +179,13 @@ impl MintDatabase for MintMemoryDatabase {
         Ok(())
     }
 
-    async fn add_spent_proof(&self, proof: Proof) -> Result<(), Self::Err> {
-        let secret_point = hash_to_curve(&proof.secret.to_bytes())?;
-        self.spent_proofs
-            .write()
-            .await
-            .insert(secret_point.to_bytes(), proof);
+    async fn add_spent_proofs(&self, spent_proofs: Proofs) -> Result<(), Self::Err> {
+        let mut proofs = self.spent_proofs.write().await;
+
+        for proof in spent_proofs {
+            let secret_point = hash_to_curve(&proof.secret.to_bytes())?;
+            proofs.insert(secret_point.to_bytes(), proof);
+        }
         Ok(())
     }
 
@@ -201,11 +202,12 @@ impl MintDatabase for MintMemoryDatabase {
         Ok(self.spent_proofs.read().await.get(&y.to_bytes()).cloned())
     }
 
-    async fn add_pending_proof(&self, proof: Proof) -> Result<(), Self::Err> {
-        self.pending_proofs
-            .write()
-            .await
-            .insert(hash_to_curve(&proof.secret.to_bytes())?.to_bytes(), proof);
+    async fn add_pending_proofs(&self, pending_proofs: Proofs) -> Result<(), Self::Err> {
+        let mut proofs = self.pending_proofs.write().await;
+
+        for proof in pending_proofs {
+            proofs.insert(hash_to_curve(&proof.secret.to_bytes())?.to_bytes(), proof);
+        }
         Ok(())
     }
 
@@ -226,12 +228,14 @@ impl MintDatabase for MintMemoryDatabase {
         Ok(self.pending_proofs.read().await.get(&y.to_bytes()).cloned())
     }
 
-    async fn remove_pending_proof(&self, secret: &Secret) -> Result<(), Self::Err> {
-        let secret_point = hash_to_curve(&secret.to_bytes())?;
-        self.pending_proofs
-            .write()
-            .await
-            .remove(&secret_point.to_bytes());
+    async fn remove_pending_proofs(&self, secrets: Vec<&Secret>) -> Result<(), Self::Err> {
+        let mut proofs = self.pending_proofs.write().await;
+
+        for secret in secrets {
+            let secret_point = hash_to_curve(&secret.to_bytes())?;
+            proofs.remove(&secret_point.to_bytes());
+        }
+
         Ok(())
     }
 

+ 5 - 5
crates/cdk/src/cdk_database/mod.rs

@@ -15,9 +15,9 @@ use crate::nuts::State;
 #[cfg(feature = "mint")]
 use crate::nuts::{BlindSignature, MeltQuoteState, MintQuoteState, Proof};
 #[cfg(any(feature = "wallet", feature = "mint"))]
-use crate::nuts::{CurrencyUnit, Id, PublicKey};
+use crate::nuts::{CurrencyUnit, Id, Proofs, PublicKey};
 #[cfg(feature = "wallet")]
-use crate::nuts::{KeySetInfo, Keys, MintInfo, Proofs, SpendingConditions};
+use crate::nuts::{KeySetInfo, Keys, MintInfo, SpendingConditions};
 #[cfg(feature = "mint")]
 use crate::secret::Secret;
 #[cfg(feature = "wallet")]
@@ -150,17 +150,17 @@ pub trait MintDatabase {
     async fn get_keyset_info(&self, id: &Id) -> Result<Option<MintKeySetInfo>, Self::Err>;
     async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err>;
 
-    async fn add_spent_proof(&self, proof: Proof) -> Result<(), Self::Err>;
+    async fn add_spent_proofs(&self, proof: Proofs) -> Result<(), Self::Err>;
     async fn get_spent_proof_by_secret(&self, secret: &Secret) -> Result<Option<Proof>, Self::Err>;
     async fn get_spent_proof_by_y(&self, y: &PublicKey) -> Result<Option<Proof>, Self::Err>;
 
-    async fn add_pending_proof(&self, proof: Proof) -> Result<(), Self::Err>;
+    async fn add_pending_proofs(&self, proof: Proofs) -> Result<(), Self::Err>;
     async fn get_pending_proof_by_secret(
         &self,
         secret: &Secret,
     ) -> Result<Option<Proof>, Self::Err>;
     async fn get_pending_proof_by_y(&self, y: &PublicKey) -> Result<Option<Proof>, Self::Err>;
-    async fn remove_pending_proof(&self, secret: &Secret) -> Result<(), Self::Err>;
+    async fn remove_pending_proofs(&self, secret: Vec<&Secret>) -> Result<(), Self::Err>;
 
     async fn add_blinded_signature(
         &self,

+ 18 - 10
crates/cdk/src/mint/mod.rs

@@ -493,9 +493,9 @@ impl Mint {
             }
         }
 
-        for proof in swap_request.inputs {
-            self.localstore.add_spent_proof(proof).await?;
-        }
+        self.localstore
+            .add_spent_proofs(swap_request.inputs)
+            .await?;
 
         let mut promises = Vec::with_capacity(swap_request.outputs.len());
 
@@ -583,6 +583,14 @@ impl Mint {
         &self,
         melt_request: &MeltBolt11Request,
     ) -> Result<MeltQuote, Error> {
+        for proof in &melt_request.inputs {
+            self.verify_proof(proof).await?;
+        }
+
+        self.localstore
+            .add_pending_proofs(melt_request.inputs.clone())
+            .await?;
+
         let state = self
             .localstore
             .update_melt_quote_state(&melt_request.quote, MeltQuoteState::Pending)
@@ -681,10 +689,6 @@ impl Mint {
             return Err(Error::DuplicateProofs);
         }
 
-        for proof in &melt_request.inputs {
-            self.verify_proof(proof).await?;
-        }
-
         Ok(quote)
     }
 
@@ -714,9 +718,9 @@ impl Mint {
             }
         }
 
-        for input in &melt_request.inputs {
-            self.localstore.add_spent_proof(input.clone()).await?;
-        }
+        self.localstore
+            .add_spent_proofs(melt_request.inputs.clone())
+            .await?;
 
         let mut change = None;
 
@@ -761,6 +765,10 @@ impl Mint {
         }
 
         self.localstore
+            .remove_pending_proofs(melt_request.inputs.iter().map(|p| &p.secret).collect())
+            .await?;
+
+        self.localstore
             .update_melt_quote_state(&melt_request.quote, MeltQuoteState::Paid)
             .await?;