refactor: move quote_ttl to database

This commit is contained in:
thesimplekid
2025-01-29 23:58:13 +00:00
parent 5481286ec9
commit c455809812
12 changed files with 144 additions and 37 deletions

View File

@@ -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>;
}

View File

@@ -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,

View File

@@ -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,

View File

@@ -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())
}
}

View File

@@ -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 {

View File

@@ -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> {

View File

@@ -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())
}
}

View File

@@ -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(),

View File

@@ -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));
}

View File

@@ -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,
);

View File

@@ -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");

View File

@@ -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,