mirror of
https://github.com/aljazceru/cdk.git
synced 2025-12-19 21:55:03 +01:00
feat: store melt_quote_id for proof
This commit is contained in:
@@ -8,7 +8,7 @@ use cdk::mint_url::MintUrl;
|
|||||||
use cdk::nuts::{CurrencyUnit, MintQuoteState, Proof, State};
|
use cdk::nuts::{CurrencyUnit, MintQuoteState, Proof, State};
|
||||||
use cdk::Amount;
|
use cdk::Amount;
|
||||||
use lightning_invoice::Bolt11Invoice;
|
use lightning_invoice::Bolt11Invoice;
|
||||||
use redb::{Database, ReadableTable, TableDefinition};
|
use redb::{Database, MultimapTableDefinition, ReadableTable, TableDefinition};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::{Error, PROOFS_STATE_TABLE, PROOFS_TABLE};
|
use super::{Error, PROOFS_STATE_TABLE, PROOFS_TABLE};
|
||||||
@@ -17,6 +17,8 @@ const MINT_QUOTES_TABLE: TableDefinition<&str, &str> = TableDefinition::new("min
|
|||||||
const PENDING_PROOFS_TABLE: TableDefinition<[u8; 33], &str> =
|
const PENDING_PROOFS_TABLE: TableDefinition<[u8; 33], &str> =
|
||||||
TableDefinition::new("pending_proofs");
|
TableDefinition::new("pending_proofs");
|
||||||
const SPENT_PROOFS_TABLE: TableDefinition<[u8; 33], &str> = TableDefinition::new("spent_proofs");
|
const SPENT_PROOFS_TABLE: TableDefinition<[u8; 33], &str> = TableDefinition::new("spent_proofs");
|
||||||
|
const QUOTE_PROOFS_TABLE: MultimapTableDefinition<&str, [u8; 33]> =
|
||||||
|
MultimapTableDefinition::new("quote_proofs");
|
||||||
|
|
||||||
pub fn migrate_01_to_02(db: Arc<Database>) -> Result<u32, Error> {
|
pub fn migrate_01_to_02(db: Arc<Database>) -> Result<u32, Error> {
|
||||||
migrate_mint_quotes_01_to_02(db)?;
|
migrate_mint_quotes_01_to_02(db)?;
|
||||||
@@ -27,6 +29,11 @@ pub fn migrate_02_to_03(db: Arc<Database>) -> Result<u32, Error> {
|
|||||||
migrate_mint_proofs_02_to_03(db)?;
|
migrate_mint_proofs_02_to_03(db)?;
|
||||||
Ok(3)
|
Ok(3)
|
||||||
}
|
}
|
||||||
|
pub fn migrate_03_to_04(db: Arc<Database>) -> Result<u32, Error> {
|
||||||
|
let write_txn = db.begin_write()?;
|
||||||
|
let _ = write_txn.open_multimap_table(QUOTE_PROOFS_TABLE)?;
|
||||||
|
Ok(4)
|
||||||
|
}
|
||||||
|
|
||||||
/// Mint Quote Info
|
/// Mint Quote Info
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ use cdk::nuts::{
|
|||||||
};
|
};
|
||||||
use cdk::{cdk_database, mint};
|
use cdk::{cdk_database, mint};
|
||||||
use migrations::migrate_01_to_02;
|
use migrations::migrate_01_to_02;
|
||||||
use redb::{Database, ReadableTable, TableDefinition};
|
use redb::{Database, MultimapTableDefinition, ReadableTable, TableDefinition};
|
||||||
|
|
||||||
use super::error::Error;
|
use super::error::Error;
|
||||||
use crate::migrations::migrate_00_to_01;
|
use crate::migrations::migrate_00_to_01;
|
||||||
use crate::mint::migrations::migrate_02_to_03;
|
use crate::mint::migrations::{migrate_02_to_03, migrate_03_to_04};
|
||||||
|
|
||||||
mod migrations;
|
mod migrations;
|
||||||
|
|
||||||
@@ -34,8 +34,10 @@ const CONFIG_TABLE: TableDefinition<&str, &str> = TableDefinition::new("config")
|
|||||||
// Key is hex blinded_message B_ value is blinded_signature
|
// Key is hex blinded_message B_ value is blinded_signature
|
||||||
const BLINDED_SIGNATURES: TableDefinition<[u8; 33], &str> =
|
const BLINDED_SIGNATURES: TableDefinition<[u8; 33], &str> =
|
||||||
TableDefinition::new("blinded_signatures");
|
TableDefinition::new("blinded_signatures");
|
||||||
|
const QUOTE_PROOFS_TABLE: MultimapTableDefinition<&str, [u8; 33]> =
|
||||||
|
MultimapTableDefinition::new("quote_proofs");
|
||||||
|
|
||||||
const DATABASE_VERSION: u32 = 3;
|
const DATABASE_VERSION: u32 = 4;
|
||||||
|
|
||||||
/// Mint Redbdatabase
|
/// Mint Redbdatabase
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -81,6 +83,10 @@ impl MintRedbDatabase {
|
|||||||
current_file_version = migrate_02_to_03(Arc::clone(&db))?;
|
current_file_version = migrate_02_to_03(Arc::clone(&db))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if current_file_version == 3 {
|
||||||
|
current_file_version = migrate_03_to_04(Arc::clone(&db))?;
|
||||||
|
}
|
||||||
|
|
||||||
if current_file_version != DATABASE_VERSION {
|
if current_file_version != DATABASE_VERSION {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
"Database upgrade did not complete at {} current is {}",
|
"Database upgrade did not complete at {} current is {}",
|
||||||
@@ -125,6 +131,7 @@ impl MintRedbDatabase {
|
|||||||
let _ = write_txn.open_table(PROOFS_TABLE)?;
|
let _ = write_txn.open_table(PROOFS_TABLE)?;
|
||||||
let _ = write_txn.open_table(PROOFS_STATE_TABLE)?;
|
let _ = write_txn.open_table(PROOFS_STATE_TABLE)?;
|
||||||
let _ = write_txn.open_table(BLINDED_SIGNATURES)?;
|
let _ = write_txn.open_table(BLINDED_SIGNATURES)?;
|
||||||
|
let _ = write_txn.open_multimap_table(QUOTE_PROOFS_TABLE)?;
|
||||||
|
|
||||||
table.insert("db_version", DATABASE_VERSION.to_string().as_str())?;
|
table.insert("db_version", DATABASE_VERSION.to_string().as_str())?;
|
||||||
}
|
}
|
||||||
@@ -483,21 +490,31 @@ impl MintDatabase for MintRedbDatabase {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_proofs(&self, proofs: Proofs) -> Result<(), Self::Err> {
|
async fn add_proofs(&self, proofs: Proofs, quote_id: Option<String>) -> Result<(), Self::Err> {
|
||||||
let write_txn = self.db.begin_write().map_err(Error::from)?;
|
let write_txn = self.db.begin_write().map_err(Error::from)?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut table = write_txn.open_table(PROOFS_TABLE).map_err(Error::from)?;
|
let mut table = write_txn.open_table(PROOFS_TABLE).map_err(Error::from)?;
|
||||||
|
let mut quote_proofs_table = write_txn
|
||||||
|
.open_multimap_table(QUOTE_PROOFS_TABLE)
|
||||||
|
.map_err(Error::from)?;
|
||||||
for proof in proofs {
|
for proof in proofs {
|
||||||
let y: PublicKey = hash_to_curve(&proof.secret.to_bytes()).map_err(Error::from)?;
|
let y: PublicKey = hash_to_curve(&proof.secret.to_bytes()).map_err(Error::from)?;
|
||||||
if table.get(y.to_bytes()).map_err(Error::from)?.is_none() {
|
let y = y.to_bytes();
|
||||||
|
if table.get(y).map_err(Error::from)?.is_none() {
|
||||||
table
|
table
|
||||||
.insert(
|
.insert(
|
||||||
y.to_bytes(),
|
y,
|
||||||
serde_json::to_string(&proof).map_err(Error::from)?.as_str(),
|
serde_json::to_string(&proof).map_err(Error::from)?.as_str(),
|
||||||
)
|
)
|
||||||
.map_err(Error::from)?;
|
.map_err(Error::from)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(quote_id) = "e_id {
|
||||||
|
quote_proofs_table
|
||||||
|
.insert(quote_id.as_str(), y)
|
||||||
|
.map_err(Error::from)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write_txn.commit().map_err(Error::from)?;
|
write_txn.commit().map_err(Error::from)?;
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE proof ADD COLUMN quote_id TEXT;
|
||||||
@@ -746,14 +746,14 @@ FROM keyset;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_proofs(&self, proofs: Proofs) -> Result<(), Self::Err> {
|
async fn add_proofs(&self, proofs: Proofs, quote_id: Option<String>) -> Result<(), Self::Err> {
|
||||||
let mut transaction = self.pool.begin().await.map_err(Error::from)?;
|
let mut transaction = self.pool.begin().await.map_err(Error::from)?;
|
||||||
for proof in proofs {
|
for proof in proofs {
|
||||||
if let Err(err) = sqlx::query(
|
if let Err(err) = sqlx::query(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO proof
|
INSERT INTO proof
|
||||||
(y, amount, keyset_id, secret, c, witness, state)
|
(y, amount, keyset_id, secret, c, witness, state, quote_id)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?);
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?);
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(proof.y()?.to_bytes().to_vec())
|
.bind(proof.y()?.to_bytes().to_vec())
|
||||||
@@ -763,6 +763,7 @@ VALUES (?, ?, ?, ?, ?, ?, ?);
|
|||||||
.bind(proof.c.to_bytes().to_vec())
|
.bind(proof.c.to_bytes().to_vec())
|
||||||
.bind(proof.witness.map(|w| serde_json::to_string(&w).unwrap()))
|
.bind(proof.witness.map(|w| serde_json::to_string(&w).unwrap()))
|
||||||
.bind("UNSPENT")
|
.bind("UNSPENT")
|
||||||
|
.bind(quote_id.clone())
|
||||||
.execute(&mut transaction)
|
.execute(&mut transaction)
|
||||||
.await
|
.await
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
@@ -774,6 +775,7 @@ VALUES (?, ?, ?, ?, ?, ?, ?);
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result<Vec<Option<Proof>>, Self::Err> {
|
async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result<Vec<Option<Proof>>, Self::Err> {
|
||||||
let mut transaction = self.pool.begin().await.map_err(Error::from)?;
|
let mut transaction = self.pool.begin().await.map_err(Error::from)?;
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ pub struct MintMemoryDatabase {
|
|||||||
melt_quotes: Arc<RwLock<HashMap<String, mint::MeltQuote>>>,
|
melt_quotes: Arc<RwLock<HashMap<String, mint::MeltQuote>>>,
|
||||||
proofs: Arc<RwLock<HashMap<[u8; 33], Proof>>>,
|
proofs: Arc<RwLock<HashMap<[u8; 33], Proof>>>,
|
||||||
proof_state: Arc<Mutex<HashMap<[u8; 33], nut07::State>>>,
|
proof_state: Arc<Mutex<HashMap<[u8; 33], nut07::State>>>,
|
||||||
|
quote_proofs: Arc<Mutex<HashMap<String, Vec<PublicKey>>>>,
|
||||||
blinded_signatures: Arc<RwLock<HashMap<[u8; 33], BlindSignature>>>,
|
blinded_signatures: Arc<RwLock<HashMap<[u8; 33], BlindSignature>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@ impl MintMemoryDatabase {
|
|||||||
melt_quotes: Vec<mint::MeltQuote>,
|
melt_quotes: Vec<mint::MeltQuote>,
|
||||||
pending_proofs: Proofs,
|
pending_proofs: Proofs,
|
||||||
spent_proofs: Proofs,
|
spent_proofs: Proofs,
|
||||||
|
quote_proofs: HashMap<String, Vec<PublicKey>>,
|
||||||
blinded_signatures: HashMap<[u8; 33], BlindSignature>,
|
blinded_signatures: HashMap<[u8; 33], BlindSignature>,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let mut proofs = HashMap::new();
|
let mut proofs = HashMap::new();
|
||||||
@@ -68,6 +70,7 @@ impl MintMemoryDatabase {
|
|||||||
proofs: Arc::new(RwLock::new(proofs)),
|
proofs: Arc::new(RwLock::new(proofs)),
|
||||||
proof_state: Arc::new(Mutex::new(proof_states)),
|
proof_state: Arc::new(Mutex::new(proof_states)),
|
||||||
blinded_signatures: Arc::new(RwLock::new(blinded_signatures)),
|
blinded_signatures: Arc::new(RwLock::new(blinded_signatures)),
|
||||||
|
quote_proofs: Arc::new(Mutex::new(quote_proofs)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,13 +222,26 @@ impl MintDatabase for MintMemoryDatabase {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_proofs(&self, proofs: Proofs) -> Result<(), Self::Err> {
|
async fn add_proofs(&self, proofs: Proofs, quote_id: Option<String>) -> Result<(), Self::Err> {
|
||||||
let mut db_proofs = self.proofs.write().await;
|
let mut db_proofs = self.proofs.write().await;
|
||||||
|
|
||||||
|
let mut ys = Vec::with_capacity(proofs.capacity());
|
||||||
|
|
||||||
for proof in proofs {
|
for proof in proofs {
|
||||||
let secret_point = hash_to_curve(&proof.secret.to_bytes())?;
|
let y = hash_to_curve(&proof.secret.to_bytes())?;
|
||||||
db_proofs.insert(secret_point.to_bytes(), proof);
|
ys.push(y);
|
||||||
|
|
||||||
|
let y = y.to_bytes();
|
||||||
|
|
||||||
|
db_proofs.insert(y, proof);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(quote_id) = quote_id {
|
||||||
|
let mut db_quote_proofs = self.quote_proofs.lock().await;
|
||||||
|
|
||||||
|
db_quote_proofs.insert(quote_id, ys);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ pub trait MintDatabase {
|
|||||||
async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err>;
|
async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err>;
|
||||||
|
|
||||||
/// Add spent [`Proofs`]
|
/// Add spent [`Proofs`]
|
||||||
async fn add_proofs(&self, proof: Proofs) -> Result<(), Self::Err>;
|
async fn add_proofs(&self, proof: Proofs, quote_id: Option<String>) -> Result<(), Self::Err>;
|
||||||
/// Get [`Proofs`] by ys
|
/// Get [`Proofs`] by ys
|
||||||
async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result<Vec<Option<Proof>>, Self::Err>;
|
async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result<Vec<Option<Proof>>, Self::Err>;
|
||||||
/// Get [`Proofs`] state
|
/// Get [`Proofs`] state
|
||||||
|
|||||||
@@ -783,7 +783,7 @@ impl Mint {
|
|||||||
.collect::<Result<Vec<PublicKey>, _>>()?;
|
.collect::<Result<Vec<PublicKey>, _>>()?;
|
||||||
|
|
||||||
self.localstore
|
self.localstore
|
||||||
.add_proofs(swap_request.inputs.clone())
|
.add_proofs(swap_request.inputs.clone(), None)
|
||||||
.await?;
|
.await?;
|
||||||
self.check_ys_spendable(&input_ys, State::Pending).await?;
|
self.check_ys_spendable(&input_ys, State::Pending).await?;
|
||||||
|
|
||||||
@@ -1024,7 +1024,10 @@ impl Mint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.localstore
|
self.localstore
|
||||||
.add_proofs(melt_request.inputs.clone())
|
.add_proofs(
|
||||||
|
melt_request.inputs.clone(),
|
||||||
|
Some(melt_request.quote.clone()),
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
self.check_ys_spendable(&ys, State::Pending).await?;
|
self.check_ys_spendable(&ys, State::Pending).await?;
|
||||||
|
|
||||||
@@ -1549,6 +1552,7 @@ mod tests {
|
|||||||
pending_proofs: Proofs,
|
pending_proofs: Proofs,
|
||||||
spent_proofs: Proofs,
|
spent_proofs: Proofs,
|
||||||
blinded_signatures: HashMap<[u8; 33], BlindSignature>,
|
blinded_signatures: HashMap<[u8; 33], BlindSignature>,
|
||||||
|
quote_proofs: HashMap<String, Vec<PublicKey>>,
|
||||||
mint_url: &'a str,
|
mint_url: &'a str,
|
||||||
seed: &'a [u8],
|
seed: &'a [u8],
|
||||||
mint_info: MintInfo,
|
mint_info: MintInfo,
|
||||||
@@ -1564,6 +1568,7 @@ mod tests {
|
|||||||
config.melt_quotes,
|
config.melt_quotes,
|
||||||
config.pending_proofs,
|
config.pending_proofs,
|
||||||
config.spent_proofs,
|
config.spent_proofs,
|
||||||
|
config.quote_proofs,
|
||||||
config.blinded_signatures,
|
config.blinded_signatures,
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
|||||||
11
flake.nix
11
flake.nix
@@ -70,17 +70,18 @@
|
|||||||
lnd
|
lnd
|
||||||
clightning
|
clightning
|
||||||
bitcoind
|
bitcoind
|
||||||
|
sqlx-cli
|
||||||
] ++ libsDarwin;
|
] ++ libsDarwin;
|
||||||
|
|
||||||
# WASM deps
|
# WASM deps
|
||||||
WASMInputs = with pkgs; [
|
# WASMInputs = with pkgs; [
|
||||||
];
|
# ];
|
||||||
|
|
||||||
nativeBuildInputs = with pkgs; [
|
# nativeBuildInputs = with pkgs; [
|
||||||
# Add additional build inputs here
|
# Add additional build inputs here
|
||||||
] ++ lib.optionals isDarwin [
|
#] ++ lib.optionals isDarwin [
|
||||||
# Additional darwin specific native inputs can be set here
|
# Additional darwin specific native inputs can be set here
|
||||||
];
|
# ];
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
checks = {
|
checks = {
|
||||||
|
|||||||
Reference in New Issue
Block a user