Explorar o código

Introduce MintKeysTransaction

This trait will let the mint have a copy of the keysets
Cesar Rodas hai 2 meses
pai
achega
b2f72ad803

+ 18 - 0
crates/cdk-common/src/database/mint/mod.rs

@@ -364,6 +364,23 @@ pub trait SignaturesDatabase {
     async fn get_total_issued(&self) -> Result<HashMap<Id, Amount>, Self::Err>;
 }
 
+/// Mint Keys transaction
+///
+/// This trait is used to call everytime the mint has new information from the Signatory, so the
+/// mint can prepare their database for the known keysets
+#[async_trait]
+pub trait MintKeysTransaction<'a> {
+    /// Database Error
+    type Err: Into<Error> + From<Error>;
+
+    /// Function to call everytime the signatory pushes information towards the mint
+    async fn set_signatory_keysets(
+        &mut self,
+        pubkey: &PublicKey,
+        keysets: &[MintKeySetInfo],
+    ) -> Result<(), Self::Err>;
+}
+
 #[async_trait]
 /// Saga Transaction trait
 pub trait SagaTransaction<'a> {
@@ -460,6 +477,7 @@ pub trait Transaction<'a, Error>:
     + ProofsTransaction<'a, Err = Error>
     + KVStoreTransaction<'a, Error>
     + SagaTransaction<'a, Err = Error>
+    + MintKeysTransaction<'a, Err = Error>
 {
 }
 

+ 4 - 3
crates/cdk-common/src/database/mod.rs

@@ -10,9 +10,10 @@ pub use mint::{
     Database as MintDatabase, DbTransactionFinalizer as MintDbWriterFinalizer, DynMintDatabase,
     KVStore as MintKVStore, KVStoreDatabase as MintKVStoreDatabase,
     KVStoreTransaction as MintKVStoreTransaction, KeysDatabase as MintKeysDatabase,
-    KeysDatabaseTransaction as MintKeyDatabaseTransaction, ProofsDatabase as MintProofsDatabase,
-    ProofsTransaction as MintProofsTransaction, QuotesDatabase as MintQuotesDatabase,
-    QuotesTransaction as MintQuotesTransaction, SignaturesDatabase as MintSignaturesDatabase,
+    KeysDatabaseTransaction as MintKeyDatabaseTransaction, MintKeysTransaction,
+    ProofsDatabase as MintProofsDatabase, ProofsTransaction as MintProofsTransaction,
+    QuotesDatabase as MintQuotesDatabase, QuotesTransaction as MintQuotesTransaction,
+    SignaturesDatabase as MintSignaturesDatabase,
     SignaturesTransaction as MintSignatureTransaction, Transaction as MintTransaction,
 };
 #[cfg(all(feature = "mint", feature = "auth"))]

+ 42 - 51
crates/cdk-sql-common/src/mint/mod.rs

@@ -129,6 +129,48 @@ where
 }
 
 #[async_trait]
+impl<RM> database::MintKeysTransaction<'_> for SQLTransaction<RM>
+where
+    RM: DatabasePool + 'static,
+{
+    /// Database Error
+    type Err = Error;
+
+    /// Function to call everytime the signatory pushes information towards the mint
+    async fn set_signatory_keysets(
+        &mut self,
+        _pubkey: &PublicKey,
+        keysets: &[MintKeySetInfo],
+    ) -> Result<(), Self::Err> {
+        let known_keysets = query("SELECT keyset_id FROM keyset_amounts")?
+            .fetch_all(&self.inner)
+            .await?
+            .into_iter()
+            .map(|mut row| {
+                Ok(column_as_string!(
+                    row.remove(0),
+                    Id::from_str,
+                    Id::from_bytes
+                ))
+            })
+            .collect::<Result<HashSet<_>, Error>>()?;
+
+        for keyset in keysets {
+            if known_keysets.contains(&keyset.id) || keyset.unit == CurrencyUnit::Auth {
+                continue;
+            }
+
+            query(r#"INSERT INTO keyset_amounts VALUES(:keyset_id, 0, 0)"#)?
+                .bind("keyset_id", keyset.id.to_string())
+                .execute(&self.inner)
+                .await?;
+        }
+
+        Ok(())
+    }
+}
+
+#[async_trait]
 impl<RM> database::MintProofsTransaction<'_> for SQLTransaction<RM>
 where
     RM: DatabasePool + 'static,
@@ -222,26 +264,6 @@ where
         if new_state == State::Spent {
             query(
                 r#"
-                INSERT INTO keyset_amounts (keyset_id, total_issued, total_redeemed)
-                SELECT p.keyset_id, 0, 0
-                FROM (
-                  SELECT DISTINCT keyset_id
-                  FROM proof
-                  WHERE y IN (:ys)
-                ) AS p
-                WHERE NOT EXISTS (
-                  SELECT 1
-                  FROM keyset_amounts ka
-                  WHERE ka.keyset_id = p.keyset_id
-                )
-            "#,
-            )?
-            .bind_vec("ys", ys.iter().map(|y| y.to_bytes().to_vec()).collect())
-            .execute(&self.inner)
-            .await?;
-
-            query(
-                r#"
                 UPDATE keyset_amounts
                 SET total_redeemed = total_redeemed + amounts.total
                 FROM (
@@ -1726,37 +1748,6 @@ where
         })
         .collect::<Result<HashMap<_, _>, Error>>()?;
 
-        let mut keysets = query("SELECT keyset_id FROM keyset_amounts")?
-            .fetch_all(&self.inner)
-            .await?
-            .into_iter()
-            .map(|mut row| {
-                Ok(column_as_string!(
-                    &row.remove(0),
-                    Id::from_str,
-                    Id::from_bytes
-                ))
-            })
-            .collect::<Result<HashSet<_>, Error>>()?;
-
-        for s in blind_signatures.iter() {
-            if keysets.contains(&s.keyset_id) {
-                continue;
-            }
-
-            keysets.insert(s.keyset_id);
-
-            query(
-                r#"
-                INSERT INTO keyset_amounts (keyset_id, total_issued, total_redeemed)
-                VALUES (:keyset, 0, 0)
-            "#,
-            )?
-            .bind("keyset", s.keyset_id.to_string())
-            .execute(&self.inner)
-            .await?;
-        }
-
         // Iterate over the provided blinded messages and signatures
         for (message, signature) in blinded_messages.iter().zip(blind_signatures) {
             match existing_rows.remove(message) {

+ 13 - 1
crates/cdk/src/mint/keysets/mod.rs

@@ -88,7 +88,19 @@ impl Mint {
             .await?;
 
         let new_keyset = self.signatory.keysets().await?;
-        self.keysets.store(new_keyset.keysets.into());
+        self.keysets.store(new_keyset.keysets.clone().into());
+
+        let mut tx = self.localstore.begin_transaction().await?;
+        tx.set_signatory_keysets(
+            &new_keyset.pubkey,
+            &new_keyset
+                .keysets
+                .iter()
+                .map(|x| x.into())
+                .collect::<Vec<_>>(),
+        )
+        .await?;
+        tx.commit().await?;
 
         Ok(result.into())
     }

+ 13 - 21
crates/cdk/src/mint/mod.rs

@@ -144,6 +144,14 @@ impl Mint {
             return Err(Error::NoActiveKeyset);
         }
 
+        let mut tx = localstore.begin_transaction().await?;
+        tx.set_signatory_keysets(
+            &keysets.pubkey,
+            &keysets.keysets.iter().map(|x| x.into()).collect::<Vec<_>>(),
+        )
+        .await?;
+        tx.commit().await?;
+
         tracing::info!(
             "Using Signatory {} with {} active keys",
             signatory.name(),
@@ -950,16 +958,7 @@ impl Mint {
         #[cfg(feature = "prometheus")]
         global::inc_in_flight_requests("total_issued");
 
-        let result = async {
-            let keysets = self.keysets().keysets;
-            let mut total_issued = self.localstore.get_total_issued().await?;
-            for keyset in keysets.into_iter().filter(|x| x.unit != CurrencyUnit::Auth) {
-                let _ = total_issued.entry(keyset.id).or_default();
-            }
-
-            Ok(total_issued)
-        }
-        .await;
+        let result = async { Ok(self.localstore.get_total_issued().await?) }.await;
 
         #[cfg(feature = "prometheus")]
         {
@@ -976,21 +975,12 @@ impl Mint {
         #[cfg(feature = "prometheus")]
         global::inc_in_flight_requests("total_redeemed");
 
-        let keysets = self.signatory.keysets().await?;
-        let mut total_redeemed = self.localstore.get_total_redeemed().await?;
-
-        for keyset in keysets
-            .keysets
-            .into_iter()
-            .filter(|x| x.unit != CurrencyUnit::Auth)
-        {
-            let _ = total_redeemed.entry(keyset.id).or_default();
-        }
+        let total_redeemed = async { Ok(self.localstore.get_total_redeemed().await?) }.await;
 
         #[cfg(feature = "prometheus")]
         global::dec_in_flight_requests("total_redeemed");
 
-        Ok(total_redeemed)
+        total_redeemed
     }
 }
 
@@ -1057,6 +1047,8 @@ mod tests {
         };
         let mint = create_mint(config).await;
 
+        println!("{:?}", mint.total_issued().await);
+
         assert_eq!(
             mint.total_issued()
                 .await