Forráskód Böngészése

refactor: move quote_ttl to database

thesimplekid 2 hónapja
szülő
commit
c455809812

+ 6 - 1
crates/cdk-common/src/database/mint.rs

@@ -7,7 +7,7 @@ use cashu::MintInfo;
 use uuid::Uuid;
 
 use super::Error;
-use crate::common::LnKey;
+use crate::common::{LnKey, QuoteTTL};
 use crate::mint::{self, MintKeySetInfo, MintQuote as MintMintQuote};
 use crate::nuts::{
     BlindSignature, CurrencyUnit, Id, MeltBolt11Request, MeltQuoteState, MintQuoteState, Proof,
@@ -133,4 +133,9 @@ pub trait Database {
     async fn set_mint_info(&self, mint_info: MintInfo) -> Result<(), Self::Err>;
     /// Get [`MintInfo`]
     async fn get_mint_info(&self) -> Result<MintInfo, Self::Err>;
+
+    /// Set [`QuoteTTL`]
+    async fn set_quote_ttl(&self, quote_ttl: QuoteTTL) -> Result<(), Self::Err>;
+    /// Get [`QuoteTTL`]
+    async fn get_quote_ttl(&self) -> Result<QuoteTTL, Self::Err>;
 }

+ 0 - 1
crates/cdk-integration-tests/tests/mint.rs

@@ -54,7 +54,6 @@ async fn new_mint(fee: u64) -> Mint {
 
     Mint::new(
         &mnemonic.to_seed_normalized(""),
-        quote_ttl,
         Arc::new(localstore),
         HashMap::new(),
         supported_units,

+ 3 - 0
crates/cdk-redb/src/error.rs

@@ -52,6 +52,9 @@ pub enum Error {
     /// Unknown Mint Info
     #[error("Unknown mint info")]
     UnknownMintInfo,
+    /// Unknown quote ttl
+    #[error("Unknown quote ttl")]
+    UnknownQuoteTTL,
     /// Unknown Proof Y
     #[error("Unknown proof Y")]
     UnknownY,

+ 27 - 1
crates/cdk-redb/src/mint/mod.rs

@@ -7,7 +7,7 @@ use std::str::FromStr;
 use std::sync::Arc;
 
 use async_trait::async_trait;
-use cdk_common::common::LnKey;
+use cdk_common::common::{LnKey, QuoteTTL};
 use cdk_common::database::{self, MintDatabase};
 use cdk_common::dhke::hash_to_curve;
 use cdk_common::mint::{self, MintKeySetInfo, MintQuote};
@@ -838,4 +838,30 @@ impl MintDatabase for MintRedbDatabase {
 
         Err(Error::UnknownMintInfo.into())
     }
+
+    async fn set_quote_ttl(&self, quote_ttl: QuoteTTL) -> Result<(), Self::Err> {
+        let write_txn = self.db.begin_write().map_err(Error::from)?;
+
+        {
+            let mut table = write_txn.open_table(CONFIG_TABLE).map_err(Error::from)?;
+            table
+                .insert("quote_ttl", serde_json::to_string(&quote_ttl)?.as_str())
+                .map_err(Error::from)?;
+        }
+        write_txn.commit().map_err(Error::from)?;
+
+        Ok(())
+    }
+    async fn get_quote_ttl(&self) -> Result<QuoteTTL, Self::Err> {
+        let read_txn = self.db.begin_read().map_err(Error::from)?;
+        let table = read_txn.open_table(CONFIG_TABLE).map_err(Error::from)?;
+
+        if let Some(quote_ttl) = table.get("quote_ttl").map_err(Error::from)? {
+            let quote_ttl = serde_json::from_str(quote_ttl.value())?;
+
+            return Ok(quote_ttl);
+        }
+
+        Err(Error::UnknownQuoteTTL.into())
+    }
 }

+ 3 - 0
crates/cdk-sqlite/src/mint/error.rs

@@ -47,6 +47,9 @@ pub enum Error {
     /// Unknown Mint Info
     #[error("Unknown mint info")]
     UnknownMintInfo,
+    /// Unknown quote TTL
+    #[error("Unknown quote TTL")]
+    UnknownQuoteTTL,
 }
 
 impl From<Error> for cdk_common::database::Error {

+ 72 - 1
crates/cdk-sqlite/src/mint/mod.rs

@@ -7,7 +7,7 @@ use std::time::Duration;
 
 use async_trait::async_trait;
 use bitcoin::bip32::DerivationPath;
-use cdk_common::common::LnKey;
+use cdk_common::common::{LnKey, QuoteTTL};
 use cdk_common::database::{self, MintDatabase};
 use cdk_common::mint::{self, MintKeySetInfo, MintQuote};
 use cdk_common::nut00::ProofsMethods;
@@ -1291,6 +1291,77 @@ WHERE id=?;
             },
         }
     }
+
+    async fn set_quote_ttl(&self, quote_ttl: QuoteTTL) -> Result<(), Self::Err> {
+        let mut transaction = self.pool.begin().await.map_err(Error::from)?;
+
+        let res = sqlx::query(
+            r#"
+INSERT OR REPLACE INTO config
+(id, value)
+VALUES (?, ?);
+        "#,
+        )
+        .bind("quote_ttl")
+        .bind(serde_json::to_string(&quote_ttl)?)
+        .execute(&mut transaction)
+        .await;
+
+        match res {
+            Ok(_) => {
+                transaction.commit().await.map_err(Error::from)?;
+                Ok(())
+            }
+            Err(err) => {
+                tracing::error!("SQLite Could not update mint info");
+                if let Err(err) = transaction.rollback().await {
+                    tracing::error!("Could not rollback sql transaction: {}", err);
+                }
+
+                Err(Error::from(err).into())
+            }
+        }
+    }
+    async fn get_quote_ttl(&self) -> Result<QuoteTTL, Self::Err> {
+        let mut transaction = self.pool.begin().await.map_err(Error::from)?;
+
+        let rec = sqlx::query(
+            r#"
+SELECT *
+FROM config
+WHERE id=?;
+        "#,
+        )
+        .bind("quote_ttl")
+        .fetch_one(&mut transaction)
+        .await;
+
+        match rec {
+            Ok(rec) => {
+                transaction.commit().await.map_err(Error::from)?;
+
+                let value: String = rec.try_get("value").map_err(Error::from)?;
+
+                let quote_ttl = serde_json::from_str(&value)?;
+
+                Ok(quote_ttl)
+            }
+            Err(err) => match err {
+                sqlx::Error::RowNotFound => {
+                    transaction.commit().await.map_err(Error::from)?;
+                    return Err(Error::UnknownQuoteTTL.into());
+                }
+                _ => {
+                    return {
+                        if let Err(err) = transaction.rollback().await {
+                            tracing::error!("Could not rollback sql transaction: {}", err);
+                        }
+                        Err(Error::SQLX(err).into())
+                    }
+                }
+            },
+        }
+    }
 }
 
 fn sqlite_row_to_keyset_info(row: SqliteRow) -> Result<MintKeySetInfo, Error> {

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

@@ -4,6 +4,7 @@ use std::collections::HashMap;
 use std::sync::Arc;
 
 use async_trait::async_trait;
+use cdk_common::common::QuoteTTL;
 use cdk_common::database::{Error, MintDatabase};
 use cdk_common::mint::MintKeySetInfo;
 use cdk_common::nut00::ProofsMethods;
@@ -35,6 +36,7 @@ pub struct MintMemoryDatabase {
     quote_signatures: Arc<RwLock<HashMap<Uuid, Vec<BlindSignature>>>>,
     melt_requests: Arc<RwLock<HashMap<Uuid, (MeltBolt11Request<Uuid>, LnKey)>>>,
     mint_info: Arc<RwLock<MintInfo>>,
+    quote_ttl: Arc<RwLock<QuoteTTL>>,
 }
 
 impl MintMemoryDatabase {
@@ -52,6 +54,7 @@ impl MintMemoryDatabase {
         quote_signatures: HashMap<Uuid, Vec<BlindSignature>>,
         melt_request: Vec<(MeltBolt11Request<Uuid>, LnKey)>,
         mint_info: MintInfo,
+        quote_ttl: QuoteTTL,
     ) -> Result<Self, Error> {
         let mut proofs = HashMap::new();
         let mut proof_states = HashMap::new();
@@ -91,6 +94,7 @@ impl MintMemoryDatabase {
             quote_signatures: Arc::new(RwLock::new(quote_signatures)),
             melt_requests: Arc::new(RwLock::new(melt_requests)),
             mint_info: Arc::new(RwLock::new(mint_info)),
+            quote_ttl: Arc::new(RwLock::new(quote_ttl)),
         })
     }
 }
@@ -429,4 +433,17 @@ impl MintDatabase for MintMemoryDatabase {
 
         Ok(mint_info.clone())
     }
+
+    async fn set_quote_ttl(&self, quote_ttl: QuoteTTL) -> Result<(), Self::Err> {
+        let mut current_quote_ttl = self.quote_ttl.write().await;
+
+        *current_quote_ttl = quote_ttl;
+
+        Ok(())
+    }
+    async fn get_quote_ttl(&self) -> Result<QuoteTTL, Self::Err> {
+        let quote_ttl = self.quote_ttl.read().await;
+
+        Ok(quote_ttl.clone())
+    }
 }

+ 4 - 1
crates/cdk/src/mint/builder.rs

@@ -224,9 +224,12 @@ impl MintBuilder {
             .ok_or(anyhow!("Localstore not set"))?;
         localstore.set_mint_info(self.mint_info.clone()).await?;
 
+        localstore
+            .set_quote_ttl(self.quote_ttl.ok_or(anyhow!("Quote ttl not set"))?)
+            .await?;
+
         Ok(Mint::new(
             self.seed.as_ref().ok_or(anyhow!("Mint seed not set"))?,
-            self.quote_ttl.ok_or(anyhow!("Quote ttl not set"))?,
             localstore,
             self.ln.clone().ok_or(anyhow!("Ln backends not set"))?,
             self.supported_units.clone(),

+ 3 - 26
crates/cdk/src/mint/config.rs

@@ -7,14 +7,11 @@ use std::sync::Arc;
 use arc_swap::ArcSwap;
 
 use super::{Id, MintKeySet};
-use crate::types::QuoteTTL;
 
 /// Mint Inner configuration
 pub struct Config {
     /// Active Mint Keysets
     pub keysets: HashMap<Id, MintKeySet>,
-    /// Quotes ttl
-    pub quote_ttl: QuoteTTL,
 }
 
 /// Mint configuration
@@ -31,8 +28,8 @@ pub struct SwappableConfig {
 
 impl SwappableConfig {
     /// Creates a new configuration instance
-    pub fn new(quote_ttl: QuoteTTL, keysets: HashMap<Id, MintKeySet>) -> Self {
-        let inner = Config { keysets, quote_ttl };
+    pub fn new(keysets: HashMap<Id, MintKeySet>) -> Self {
+        let inner = Config { keysets };
 
         Self {
             config: Arc::new(ArcSwap::from_pointee(inner)),
@@ -44,29 +41,9 @@ impl SwappableConfig {
         self.config.load().clone()
     }
 
-    /// Gets a copy of the quote ttl
-    pub fn quote_ttl(&self) -> QuoteTTL {
-        self.load().quote_ttl
-    }
-
-    /// Replaces the current quote ttl with a new one
-    pub fn set_quote_ttl(&self, quote_ttl: QuoteTTL) {
-        let current_inner = self.load();
-        let new_inner = Config {
-            quote_ttl,
-            keysets: current_inner.keysets.clone(),
-        };
-
-        self.config.store(Arc::new(new_inner));
-    }
-
     /// Replaces the current keysets with a new one
     pub fn set_keysets(&self, keysets: HashMap<Id, MintKeySet>) {
-        let current_inner = self.load();
-        let new_inner = Config {
-            quote_ttl: current_inner.quote_ttl,
-            keysets,
-        };
+        let new_inner = Config { keysets };
 
         self.config.store(Arc::new(new_inner));
     }

+ 3 - 1
crates/cdk/src/mint/melt.rs

@@ -120,12 +120,14 @@ impl Mint {
         // or we want to ignore the amount and do an mpp payment
         let msats_to_pay = options.map(|opt| opt.amount_msat());
 
+        let melt_ttl = self.localstore.get_quote_ttl().await?.melt_ttl;
+
         let quote = MeltQuote::new(
             request.to_string(),
             unit.clone(),
             payment_quote.amount,
             payment_quote.fee,
-            unix_time() + self.config.quote_ttl().melt_ttl,
+            unix_time() + melt_ttl,
             payment_quote.request_lookup_id.clone(),
             msats_to_pay,
         );

+ 3 - 1
crates/cdk/src/mint/mint_nut04.rs

@@ -80,7 +80,9 @@ impl Mint {
                 Error::UnitUnsupported
             })?;
 
-        let quote_expiry = unix_time() + self.config.quote_ttl().mint_ttl;
+        let mint_ttl = self.localstore.get_quote_ttl().await?.mint_ttl;
+
+        let quote_expiry = unix_time() + mint_ttl;
 
         if description.is_some() && !ln.get_settings().invoice_description {
             tracing::error!("Backend does not support invoice description");

+ 3 - 4
crates/cdk/src/mint/mod.rs

@@ -5,7 +5,7 @@ use std::sync::Arc;
 
 use bitcoin::bip32::{ChildNumber, DerivationPath, Xpriv};
 use bitcoin::secp256k1::{self, Secp256k1};
-use cdk_common::common::{LnKey, QuoteTTL};
+use cdk_common::common::LnKey;
 use cdk_common::database::{self, MintDatabase};
 use cdk_common::mint::MintKeySetInfo;
 use config::SwappableConfig;
@@ -58,7 +58,6 @@ impl Mint {
     #[allow(clippy::too_many_arguments)]
     pub async fn new(
         seed: &[u8],
-        quote_ttl: QuoteTTL,
         localstore: Arc<dyn MintDatabase<Err = database::Error> + Send + Sync>,
         ln: HashMap<LnKey, Arc<dyn MintLightning<Err = cdk_lightning::Error> + Send + Sync>>,
         // Hashmap where the key is the unit and value is (input fee ppk, max_order)
@@ -178,7 +177,7 @@ impl Mint {
         }
 
         Ok(Self {
-            config: SwappableConfig::new(quote_ttl, active_keysets),
+            config: SwappableConfig::new(active_keysets),
             pubsub_manager: Arc::new(localstore.clone().into()),
             secp_ctx,
             xpriv,
@@ -687,13 +686,13 @@ mod tests {
                 config.quote_signatures,
                 config.melt_requests,
                 config.mint_info,
+                config.quote_ttl,
             )
             .unwrap(),
         );
 
         Mint::new(
             config.seed,
-            config.quote_ttl,
             localstore,
             HashMap::new(),
             config.supported_units,