Merge pull request #569 from thesimplekid/move_config_to_db

refactor: Move mint info and quote ttl to database
This commit is contained in:
thesimplekid
2025-01-30 09:53:48 +00:00
committed by GitHub
24 changed files with 336 additions and 266 deletions

View File

@@ -4,7 +4,6 @@ use bitcoin::bip32::DerivationPath;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::mint_url::MintUrl;
use crate::nuts::{MeltQuoteState, MintQuoteState};
use crate::{Amount, CurrencyUnit, Id, KeySetInfo, PublicKey};
@@ -13,8 +12,6 @@ use crate::{Amount, CurrencyUnit, Id, KeySetInfo, PublicKey};
pub struct MintQuote {
/// Quote id
pub id: Uuid,
/// Mint Url
pub mint_url: MintUrl,
/// Amount of quote
pub amount: Amount,
/// Unit of quote
@@ -34,7 +31,6 @@ pub struct MintQuote {
impl MintQuote {
/// Create new [`MintQuote`]
pub fn new(
mint_url: MintUrl,
request: String,
unit: CurrencyUnit,
amount: Amount,
@@ -45,7 +41,6 @@ impl MintQuote {
let id = Uuid::new_v4();
Self {
mint_url,
id,
amount,
unit,

View File

@@ -342,7 +342,18 @@ pub async fn post_check(
))]
/// Mint information, operator contact information, and other info
pub async fn get_mint_info(State(state): State<MintState>) -> Result<Json<MintInfo>, Response> {
Ok(Json(state.mint.mint_info().clone().time(unix_time())))
Ok(Json(
state
.mint
.mint_info()
.await
.map_err(|err| {
tracing::error!("Could not get mint info: {}", err);
into_response(err)
})?
.clone()
.time(unix_time()),
))
}
#[cfg_attr(feature = "swagger", utoipa::path(

View File

@@ -3,10 +3,11 @@
use std::collections::HashMap;
use async_trait::async_trait;
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,
@@ -127,4 +128,14 @@ pub trait Database {
&self,
quote_id: &Uuid,
) -> Result<Vec<BlindSignature>, Self::Err>;
/// Set [`MintInfo`]
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

@@ -50,7 +50,6 @@ where
mint_builder = mint_builder
.with_name("fake test mint".to_string())
.with_mint_url(format!("http://{addr}:{port}"))
.with_description("fake test mint".to_string())
.with_quote_ttl(10000, 10000)
.with_seed(mnemonic.to_seed_normalized("").to_vec());

View File

@@ -38,11 +38,7 @@ impl DirectMintConnection {
impl Debug for DirectMintConnection {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"DirectMintConnection {{ mint_info: {:?} }}",
self.mint.config.mint_info()
)
write!(f, "DirectMintConnection",)
}
}
@@ -130,7 +126,7 @@ impl MintConnector for DirectMintConnection {
}
async fn get_mint_info(&self) -> Result<MintInfo, Error> {
Ok(self.mint.mint_info().clone().time(unix_time()))
Ok(self.mint.mint_info().await?.clone().time(unix_time()))
}
async fn post_check_state(
@@ -175,7 +171,6 @@ pub async fn create_and_start_test_mint() -> anyhow::Result<Arc<Mint>> {
mint_builder = mint_builder
.with_name("pure test mint".to_string())
.with_mint_url("http://aa".to_string())
.with_description("pure test mint".to_string())
.with_quote_ttl(10000, 10000)
.with_seed(mnemonic.to_seed_normalized("").to_vec());
@@ -198,7 +193,7 @@ pub fn create_test_wallet_for_mint(mint: Arc<Mint>) -> anyhow::Result<Arc<Wallet
let connector = DirectMintConnection::new(mint);
let seed = Mnemonic::generate(12)?.to_seed_normalized("");
let mint_url = connector.mint.config.mint_url().to_string();
let mint_url = "http://aa".to_string();
let unit = CurrencyUnit::Sat;
let localstore = WalletMemoryDatabase::default();
let mut wallet = Wallet::new(&mint_url, unit, Arc::new(localstore), &seed, None)?;

View File

@@ -169,7 +169,6 @@ where
mint_builder = mint_builder
.with_name("regtest mint".to_string())
.with_mint_url(format!("http://{addr}:{port}"))
.with_description("regtest mint".to_string())
.with_quote_ttl(10000, 10000)
.with_seed(mnemonic.to_seed_normalized("").to_vec());

View File

@@ -8,6 +8,7 @@ use anyhow::{bail, Result};
use bip39::Mnemonic;
use cdk::amount::{Amount, SplitTarget};
use cdk::cdk_database::mint_memory::MintMemoryDatabase;
use cdk::cdk_database::MintDatabase;
use cdk::dhke::construct_proofs;
use cdk::mint::MintQuote;
use cdk::nuts::nut00::ProofsMethods;
@@ -16,7 +17,6 @@ use cdk::nuts::{
ProofState, Proofs, SecretKey, SpendingConditions, State, SwapRequest,
};
use cdk::subscription::{IndexableParams, Params};
use cdk::types::QuoteTTL;
use cdk::util::unix_time;
use cdk::Mint;
use tokio::sync::OnceCell;
@@ -41,16 +41,17 @@ async fn new_mint(fee: u64) -> Mint {
let mint_info = MintInfo::new().nuts(nuts);
let localstore = MintMemoryDatabase::default();
localstore
.set_mint_info(mint_info)
.await
.expect("Could not set mint info");
let mnemonic = Mnemonic::generate(12).unwrap();
let quote_ttl = QuoteTTL::new(10000, 10000);
Mint::new(
MINT_URL,
&mnemonic.to_seed_normalized(""),
mint_info,
quote_ttl,
Arc::new(MintMemoryDatabase::default()),
Arc::new(localstore),
HashMap::new(),
supported_units,
HashMap::new(),
@@ -72,7 +73,6 @@ async fn mint_proofs(
let request_lookup = uuid::Uuid::new_v4().to_string();
let quote = MintQuote::new(
mint.config.mint_url(),
"".to_string(),
CurrencyUnit::Sat,
amount,

View File

@@ -301,7 +301,6 @@ async fn main() -> anyhow::Result<()> {
mint_builder = mint_builder
.with_name(settings.mint_info.name)
.with_mint_url(settings.info.url)
.with_version(mint_version)
.with_description(settings.mint_info.description)
.with_quote_ttl(10000, 10000)

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

@@ -202,7 +202,6 @@ impl From<V1MintQuote> for MintQuote {
fn from(quote: V1MintQuote) -> MintQuote {
MintQuote {
id: quote.id,
mint_url: quote.mint_url,
amount: quote.amount,
unit: quote.unit,
request: quote.request.clone(),

View File

@@ -7,14 +7,14 @@ 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};
use cdk_common::nut00::ProofsMethods;
use cdk_common::{
BlindSignature, CurrencyUnit, Id, MeltBolt11Request, MeltQuoteState, MintQuoteState, Proof,
Proofs, PublicKey, State,
BlindSignature, CurrencyUnit, Id, MeltBolt11Request, MeltQuoteState, MintInfo, MintQuoteState,
Proof, Proofs, PublicKey, State,
};
use migrations::{migrate_01_to_02, migrate_04_to_05};
use redb::{Database, MultimapTableDefinition, ReadableTable, TableDefinition};
@@ -812,4 +812,56 @@ impl MintDatabase for MintRedbDatabase {
Ok(signatures)
}
async fn set_mint_info(&self, mint_info: MintInfo) -> 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("mint_info", serde_json::to_string(&mint_info)?.as_str())
.map_err(Error::from)?;
}
write_txn.commit().map_err(Error::from)?;
Ok(())
}
async fn get_mint_info(&self) -> Result<MintInfo, 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(mint_info) = table.get("mint_info").map_err(Error::from)? {
let mint_info = serde_json::from_str(mint_info.value())?;
return Ok(mint_info);
}
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

@@ -44,6 +44,12 @@ pub enum Error {
/// Serde Error
#[error(transparent)]
Serde(#[from] serde_json::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

@@ -0,0 +1 @@
ALTER TABLE mint_quote DROP COLUMN mint_url;

View File

@@ -0,0 +1,4 @@
CREATE TABLE IF NOT EXISTS config (
id TEXT PRIMARY KEY,
value TEXT NOT NULL
);

View File

@@ -7,16 +7,16 @@ 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::mint_url::MintUrl;
use cdk_common::nut00::ProofsMethods;
use cdk_common::nut05::QuoteState;
use cdk_common::secret::Secret;
use cdk_common::{
Amount, BlindSignature, BlindSignatureDleq, CurrencyUnit, Id, MeltBolt11Request,
MeltQuoteState, MintQuoteState, PaymentMethod, Proof, Proofs, PublicKey, SecretKey, State,
MeltQuoteState, MintInfo, MintQuoteState, PaymentMethod, Proof, Proofs, PublicKey, SecretKey,
State,
};
use error::Error;
use lightning_invoice::Bolt11Invoice;
@@ -206,12 +206,11 @@ WHERE active = 1
let res = sqlx::query(
r#"
INSERT OR REPLACE INTO mint_quote
(id, mint_url, amount, unit, request, state, expiry, request_lookup_id, pubkey)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);
(id, amount, unit, request, state, expiry, request_lookup_id, pubkey)
VALUES (?, ?, ?, ?, ?, ?, ?, ?);
"#,
)
.bind(quote.id.to_string())
.bind(quote.mint_url.to_string())
.bind(u64::from(quote.amount) as i64)
.bind(quote.unit.to_string())
.bind(quote.request)
@@ -1221,6 +1220,148 @@ WHERE quote_id=?;
}
}
}
async fn set_mint_info(&self, mint_info: MintInfo) -> 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("mint_info")
.bind(serde_json::to_string(&mint_info)?)
.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_mint_info(&self) -> Result<MintInfo, Self::Err> {
let mut transaction = self.pool.begin().await.map_err(Error::from)?;
let rec = sqlx::query(
r#"
SELECT *
FROM config
WHERE id=?;
"#,
)
.bind("mint_info")
.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 mint_info = serde_json::from_str(&value)?;
Ok(mint_info)
}
Err(err) => match err {
sqlx::Error::RowNotFound => {
transaction.commit().await.map_err(Error::from)?;
return Err(Error::UnknownMintInfo.into());
}
_ => {
return {
if let Err(err) = transaction.rollback().await {
tracing::error!("Could not rollback sql transaction: {}", err);
}
Err(Error::SQLX(err).into())
}
}
},
}
}
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> {
@@ -1250,7 +1391,6 @@ fn sqlite_row_to_keyset_info(row: SqliteRow) -> Result<MintKeySetInfo, Error> {
fn sqlite_row_to_mint_quote(row: SqliteRow) -> Result<MintQuote, Error> {
let row_id: Hyphenated = row.try_get("id").map_err(Error::from)?;
let row_mint_url: String = row.try_get("mint_url").map_err(Error::from)?;
let row_amount: i64 = row.try_get("amount").map_err(Error::from)?;
let row_unit: String = row.try_get("unit").map_err(Error::from)?;
let row_request: String = row.try_get("request").map_err(Error::from)?;
@@ -1274,7 +1414,6 @@ fn sqlite_row_to_mint_quote(row: SqliteRow) -> Result<MintQuote, Error> {
Ok(MintQuote {
id: row_id.into_uuid(),
mint_url: MintUrl::from_str(&row_mint_url)?,
amount: Amount::from(row_amount as u64),
unit: CurrencyUnit::from_str(&row_unit).map_err(Error::from)?,
request: row_request,

View File

@@ -23,7 +23,6 @@ http_subscription = []
[dependencies]
cdk-common = { path = "../cdk-common", version = "0.6.0" }
cbor-diag = "0.1.12"
arc-swap = "1.7.1"
async-trait = "0.1"
anyhow = { version = "1.0.43", features = ["backtrace"] }
bitcoin = { version = "0.32.2", features = [

View File

@@ -4,9 +4,11 @@ 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;
use cdk_common::MintInfo;
use tokio::sync::{Mutex, RwLock};
use uuid::Uuid;
@@ -33,6 +35,8 @@ pub struct MintMemoryDatabase {
blinded_signatures: Arc<RwLock<HashMap<[u8; 33], BlindSignature>>>,
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 {
@@ -49,6 +53,8 @@ impl MintMemoryDatabase {
blinded_signatures: HashMap<[u8; 33], BlindSignature>,
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();
@@ -87,6 +93,8 @@ impl MintMemoryDatabase {
quote_proofs: Arc::new(Mutex::new(quote_proofs)),
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)),
})
}
}
@@ -412,4 +420,30 @@ impl MintDatabase for MintMemoryDatabase {
Ok(ys.get(quote_id).cloned().unwrap_or_default())
}
async fn set_mint_info(&self, mint_info: MintInfo) -> Result<(), Self::Err> {
let mut current_mint_info = self.mint_info.write().await;
*current_mint_info = mint_info;
Ok(())
}
async fn get_mint_info(&self) -> Result<MintInfo, Self::Err> {
let mint_info = self.mint_info.read().await;
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)
}
}

View File

@@ -21,8 +21,6 @@ use crate::types::{LnKey, QuoteTTL};
/// Cashu Mint
#[derive(Default)]
pub struct MintBuilder {
/// Mint Url
mint_url: Option<String>,
/// Mint Info
mint_info: MintInfo,
/// Mint Storage backend
@@ -63,12 +61,6 @@ impl MintBuilder {
self
}
/// Set mint url
pub fn with_mint_url(mut self, mint_url: String) -> Self {
self.mint_url = Some(mint_url);
self
}
/// Set seed
pub fn with_seed(mut self, seed: Vec<u8>) -> Self {
self.seed = Some(seed);
@@ -226,14 +218,19 @@ impl MintBuilder {
/// Build mint
pub async fn build(&self) -> anyhow::Result<Mint> {
let localstore = self
.localstore
.clone()
.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.mint_url.as_ref().ok_or(anyhow!("Mint url not set"))?,
self.seed.as_ref().ok_or(anyhow!("Mint seed not set"))?,
self.mint_info.clone(),
self.quote_ttl.ok_or(anyhow!("Quote ttl not set"))?,
self.localstore
.clone()
.ok_or(anyhow!("Localstore not set"))?,
localstore,
self.ln.clone().ok_or(anyhow!("Ln backends not set"))?,
self.supported_units.clone(),
HashMap::new(),

View File

@@ -1,128 +0,0 @@
//! Active mint configuration
//!
//! This is the active configuration that can be updated at runtime.
use std::collections::HashMap;
use std::sync::Arc;
use arc_swap::ArcSwap;
use super::{Id, MintInfo, MintKeySet};
use crate::mint_url::MintUrl;
use crate::types::QuoteTTL;
/// Mint Inner configuration
pub struct Config {
/// Active Mint Keysets
pub keysets: HashMap<Id, MintKeySet>,
/// Mint url
pub mint_info: MintInfo,
/// Mint config
pub mint_url: MintUrl,
/// Quotes ttl
pub quote_ttl: QuoteTTL,
}
/// Mint configuration
///
/// This struct is used to configure the mint, and it is wrapped inside a ArcSwap, so it can be
/// updated at runtime without locking the shared config nor without requiriming a mutable reference
/// to the config
///
/// ArcSwap is used instead of a RwLock since the updates should be less frequent than the reads
#[derive(Clone)]
pub struct SwappableConfig {
config: Arc<ArcSwap<Config>>,
}
impl SwappableConfig {
/// Creates a new configuration instance
pub fn new(
mint_url: MintUrl,
quote_ttl: QuoteTTL,
mint_info: MintInfo,
keysets: HashMap<Id, MintKeySet>,
) -> Self {
let inner = Config {
keysets,
quote_ttl,
mint_info,
mint_url,
};
Self {
config: Arc::new(ArcSwap::from_pointee(inner)),
}
}
/// Gets an Arc of the current configuration
pub fn load(&self) -> Arc<Config> {
self.config.load().clone()
}
/// Gets a copy of the mint url
pub fn mint_url(&self) -> MintUrl {
self.load().mint_url.clone()
}
/// Replace the current mint url with a new one
pub fn set_mint_url(&self, mint_url: MintUrl) {
let current_inner = self.load();
let new_inner = Config {
mint_url,
quote_ttl: current_inner.quote_ttl,
mint_info: current_inner.mint_info.clone(),
keysets: current_inner.keysets.clone(),
};
self.config.store(Arc::new(new_inner));
}
/// 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 {
mint_info: current_inner.mint_info.clone(),
mint_url: current_inner.mint_url.clone(),
quote_ttl,
keysets: current_inner.keysets.clone(),
};
self.config.store(Arc::new(new_inner));
}
/// Gets a copy of the mint info
pub fn mint_info(&self) -> MintInfo {
self.load().mint_info.clone()
}
/// Replaces the current mint info with a new one
pub fn set_mint_info(&self, mint_info: MintInfo) {
let current_inner = self.load();
let new_inner = Config {
mint_info,
mint_url: current_inner.mint_url.clone(),
quote_ttl: current_inner.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 {
mint_info: current_inner.mint_info.clone(),
quote_ttl: current_inner.quote_ttl,
mint_url: current_inner.mint_url.clone(),
keysets,
};
self.config.store(Arc::new(new_inner));
}
}

View File

@@ -1,30 +0,0 @@
use tracing::instrument;
use super::{Mint, MintInfo};
use crate::mint_url::MintUrl;
impl Mint {
/// Set Mint Url
#[instrument(skip_all)]
pub fn set_mint_url(&self, mint_url: MintUrl) {
self.config.set_mint_url(mint_url);
}
/// Get Mint Url
#[instrument(skip_all)]
pub fn get_mint_url(&self) -> MintUrl {
self.config.mint_url()
}
/// Set Mint Info
#[instrument(skip_all)]
pub fn set_mint_info(&self, mint_info: MintInfo) {
self.config.set_mint_info(mint_info);
}
/// Get Mint Info
#[instrument(skip_all)]
pub fn mint_info(&self) -> MintInfo {
self.config.mint_info()
}
}

View File

@@ -16,9 +16,9 @@ impl Mint {
pub async fn keyset_pubkeys(&self, keyset_id: &Id) -> Result<KeysResponse, Error> {
self.ensure_keyset_loaded(keyset_id).await?;
let keyset = self
.config
.load()
.keysets
.read()
.await
.get(keyset_id)
.ok_or(Error::UnknownKeySet)?
.clone();
@@ -41,9 +41,9 @@ impl Mint {
Ok(KeysResponse {
keysets: self
.config
.load()
.keysets
.read()
.await
.values()
.filter_map(|k| match active_keysets.contains(&k.id) {
true => Some(k.clone().into()),
@@ -82,8 +82,7 @@ impl Mint {
#[instrument(skip(self))]
pub async fn keyset(&self, id: &Id) -> Result<Option<KeySet>, Error> {
self.ensure_keyset_loaded(id).await?;
let config = self.config.load();
let keysets = &config.keysets;
let keysets = self.keysets.read().await;
let keyset = keysets.get(id).map(|k| k.clone().into());
Ok(keyset)
}
@@ -118,9 +117,8 @@ impl Mint {
self.localstore.add_keyset_info(keyset_info).await?;
self.localstore.set_active_keyset(unit, id).await?;
let mut keysets = self.config.load().keysets.clone();
let mut keysets = self.keysets.write().await;
keysets.insert(id, keyset);
self.config.set_keysets(keysets);
Ok(())
}
@@ -128,11 +126,14 @@ impl Mint {
/// Ensure Keyset is loaded in mint
#[instrument(skip(self))]
pub async fn ensure_keyset_loaded(&self, id: &Id) -> Result<(), Error> {
if self.config.load().keysets.contains_key(id) {
return Ok(());
{
let keysets = self.keysets.read().await;
if keysets.contains_key(id) {
return Ok(());
}
}
let mut keysets = self.config.load().keysets.clone();
let mut keysets = self.keysets.write().await;
let keyset_info = self
.localstore
.get_keyset_info(id)
@@ -140,7 +141,6 @@ impl Mint {
.ok_or(Error::UnknownKeySet)?;
let id = keyset_info.id;
keysets.insert(id, self.generate_keyset(keyset_info));
self.config.set_keysets(keysets);
Ok(())
}

View File

@@ -31,7 +31,7 @@ impl Mint {
request: String,
options: Option<MeltOptions>,
) -> Result<(), Error> {
let mint_info = self.mint_info();
let mint_info = self.localstore.get_mint_info().await?;
let nut05 = mint_info.nuts.nut05;
let nut15 = mint_info.nuts.nut15;
@@ -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

@@ -12,12 +12,12 @@ use crate::{Amount, Error};
impl Mint {
/// Checks that minting is enabled, request is supported unit and within range
fn check_mint_request_acceptable(
async fn check_mint_request_acceptable(
&self,
amount: Amount,
unit: &CurrencyUnit,
) -> Result<(), Error> {
let mint_info = self.mint_info();
let mint_info = self.localstore.get_mint_info().await?;
let nut04 = &mint_info.nuts.nut04;
if nut04.disabled {
@@ -69,7 +69,7 @@ impl Mint {
pubkey,
} = mint_quote_request;
self.check_mint_request_acceptable(amount, &unit)?;
self.check_mint_request_acceptable(amount, &unit).await?;
let ln = self
.ln
@@ -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");
@@ -101,7 +103,6 @@ impl Mint {
})?;
let quote = MintQuote::new(
self.config.mint_url(),
create_invoice_response.request.to_string(),
unit.clone(),
amount,

File diff suppressed because one or more lines are too long