Explorar o código

Undo all the over-engineered solutions I proposed to try to adapt to the workload (mostly updates and rarely inserts).

I rolled back the proposed solution to the initial INSERT, which will most
likely fail and fall back to an UPDATE, but in exchange, the code is much
simpler to debug and maintain. If this approach proves to be a bottleneck in
the future, I will bring back 3ad85294898979508a218b3e03a71ad41cc00a2d, along
with mechanisms to notify the mints whenever the Signatory has new keys.
Cesar Rodas hai 1 semana
pai
achega
28a31fc3e9

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

@@ -364,23 +364,6 @@ 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> {
@@ -477,7 +460,6 @@ pub trait Transaction<'a, Error>:
     + ProofsTransaction<'a, Err = Error>
     + KVStoreTransaction<'a, Error>
     + SagaTransaction<'a, Err = Error>
-    + MintKeysTransaction<'a, Err = Error>
 {
 }
 

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

@@ -10,10 +10,9 @@ 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, MintKeysTransaction,
-    ProofsDatabase as MintProofsDatabase, ProofsTransaction as MintProofsTransaction,
-    QuotesDatabase as MintQuotesDatabase, QuotesTransaction as MintQuotesTransaction,
-    SignaturesDatabase as MintSignaturesDatabase,
+    KeysDatabaseTransaction as MintKeyDatabaseTransaction, 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"))]

+ 16 - 58
crates/cdk-sql-common/src/mint/mod.rs

@@ -8,7 +8,7 @@
 //! The trait expects an asynchronous interaction, but it also provides tools to spawn blocking
 //! clients in a pool and expose them to an asynchronous environment, making them compatible with
 //! Mint.
-use std::collections::{HashMap, HashSet};
+use std::collections::HashMap;
 use std::fmt::Debug;
 use std::str::FromStr;
 use std::sync::Arc;
@@ -129,48 +129,6 @@ 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,
@@ -264,15 +222,13 @@ where
         if new_state == State::Spent {
             query(
                 r#"
-                UPDATE keyset_amounts
-                SET total_redeemed = total_redeemed + amounts.total
-                FROM (
-                    SELECT keyset_id, COALESCE(SUM(amount), 0) as total
-                    FROM proof
-                    WHERE y IN (:ys)
-                    GROUP BY keyset_id
-                ) amounts
-                WHERE keyset_amounts.keyset_id = amounts.keyset_id
+                INSERT INTO keyset_amounts (keyset_id, total_issued, total_redeemed)
+                SELECT keyset_id, 0, COALESCE(SUM(amount), 0)
+                FROM proof
+                WHERE y IN (:ys)
+                GROUP BY keyset_id
+                ON CONFLICT (keyset_id)
+                DO UPDATE SET total_redeemed = keyset_amounts.total_redeemed + EXCLUDED.total_redeemed
                 "#,
             )?
             .bind_vec("ys", ys.iter().map(|y| y.to_bytes().to_vec()).collect())
@@ -1781,9 +1737,10 @@ where
 
                     query(
                         r#"
-                        UPDATE keyset_amounts
-                        SET total_issued = total_issued + :amount
-                        WHERE keyset_id = :keyset_id
+                        INSERT INTO keyset_amounts (keyset_id, total_issued, total_redeemed)
+                        VALUES (:keyset_id, :amount, 0)
+                        ON CONFLICT (keyset_id)
+                        DO UPDATE SET total_issued = keyset_amounts.total_issued + :amount
                         "#,
                     )?
                     .bind("amount", u64::from(signature.amount) as i64)
@@ -1820,9 +1777,10 @@ where
 
                             query(
                                 r#"
-                                UPDATE keyset_amounts
-                                SET total_issued = total_issued + :amount
-                                WHERE keyset_id = :keyset_id
+                                INSERT INTO keyset_amounts (keyset_id, total_issued, total_redeemed)
+                                VALUES (:keyset_id, :amount, 0)
+                                ON CONFLICT (keyset_id)
+                                DO UPDATE SET total_issued = keyset_amounts.total_issued + :amount
                                 "#,
                             )?
                             .bind("amount", u64::from(signature.amount) as i64)

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

@@ -88,19 +88,7 @@ impl Mint {
             .await?;
 
         let new_keyset = self.signatory.keysets().await?;
-        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?;
+        self.keysets.store(new_keyset.keysets.into());
 
         Ok(result.into())
     }

+ 0 - 8
crates/cdk/src/mint/mod.rs

@@ -144,14 +144,6 @@ 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(),