refactor: use sproof state update

This commit is contained in:
thesimplekid
2024-07-18 22:38:07 +01:00
parent 9789475686
commit fb014573c1
10 changed files with 337 additions and 272 deletions

View File

@@ -1,23 +1,31 @@
use core::str;
use std::collections::HashMap;
use std::str::FromStr;
use std::sync::Arc;
use cdk::mint::MintQuote;
use cdk::nuts::{CurrencyUnit, MintQuoteState};
use cdk::nuts::{CurrencyUnit, MintQuoteState, Proof, State};
use cdk::{Amount, UncheckedUrl};
use lightning_invoice::Bolt11Invoice;
use redb::{Database, ReadableTable, TableDefinition};
use serde::{Deserialize, Serialize};
use super::Error;
use super::{Error, PROOFS_STATE_TABLE, PROOFS_TABLE};
const MINT_QUOTES_TABLE: TableDefinition<&str, &str> = TableDefinition::new("mint_quotes");
const PENDING_PROOFS_TABLE: TableDefinition<[u8; 33], &str> =
TableDefinition::new("pending_proofs");
const SPENT_PROOFS_TABLE: TableDefinition<[u8; 33], &str> = TableDefinition::new("spent_proofs");
pub fn migrate_01_to_02(db: Arc<Database>) -> Result<u32, Error> {
migrate_mint_quotes_01_to_02(db)?;
Ok(2)
}
pub fn migrate_02_to_03(db: Arc<Database>) -> Result<u32, Error> {
migrate_mint_proofs_02_to_03(db)?;
Ok(3)
}
/// Mint Quote Info
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
struct V1MintQuote {
@@ -97,3 +105,70 @@ fn migrate_mint_quotes_01_to_02(db: Arc<Database>) -> Result<(), Error> {
Ok(())
}
fn migrate_mint_proofs_02_to_03(db: Arc<Database>) -> Result<(), Error> {
let pending_proofs: Vec<([u8; 33], Option<Proof>)>;
let spent_proofs: Vec<([u8; 33], Option<Proof>)>;
{
let read_txn = db.begin_read().map_err(Error::from)?;
let table = read_txn
.open_table(PENDING_PROOFS_TABLE)
.map_err(Error::from)?;
pending_proofs = table
.iter()
.map_err(Error::from)?
.flatten()
.map(|(quote_id, mint_quote)| {
(
quote_id.value(),
serde_json::from_str(mint_quote.value()).ok(),
)
})
.collect();
}
{
let read_txn = db.begin_read().map_err(Error::from)?;
let table = read_txn
.open_table(SPENT_PROOFS_TABLE)
.map_err(Error::from)?;
spent_proofs = table
.iter()
.map_err(Error::from)?
.flatten()
.map(|(quote_id, mint_quote)| {
(
quote_id.value(),
serde_json::from_str(mint_quote.value()).ok(),
)
})
.collect();
}
let write_txn = db.begin_write().map_err(Error::from)?;
{
let mut proofs_table = write_txn.open_table(PROOFS_TABLE).map_err(Error::from)?;
let mut state_table = write_txn
.open_table(PROOFS_STATE_TABLE)
.map_err(Error::from)?;
for (y, proof) in pending_proofs {
if let Some(proof) = proof {
proofs_table.insert(y, serde_json::to_string(&proof)?.as_str())?;
state_table.insert(y, State::Pending.to_string().as_str())?;
}
}
for (y, proof) in spent_proofs {
if let Some(proof) = proof {
proofs_table.insert(y, serde_json::to_string(&proof)?.as_str())?;
state_table.insert(y, State::Spent.to_string().as_str())?;
}
}
}
write_txn.commit()?;
Ok(())
}

View File

@@ -11,9 +11,9 @@ use cdk::cdk_database::MintDatabase;
use cdk::dhke::hash_to_curve;
use cdk::mint::{MintKeySetInfo, MintQuote};
use cdk::nuts::{
BlindSignature, CurrencyUnit, Id, MeltQuoteState, MintQuoteState, Proof, PublicKey,
BlindSignature, CurrencyUnit, Id, MeltQuoteState, MintQuoteState, Proof, Proofs, PublicKey,
State,
};
use cdk::secret::Secret;
use cdk::{cdk_database, mint};
use migrations::migrate_01_to_02;
use redb::{Database, ReadableTable, TableDefinition};
@@ -21,6 +21,7 @@ use tokio::sync::Mutex;
use super::error::Error;
use crate::migrations::migrate_00_to_01;
use crate::mint::migrations::migrate_02_to_03;
mod migrations;
@@ -28,15 +29,14 @@ const ACTIVE_KEYSETS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("
const KEYSETS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("keysets");
const MINT_QUOTES_TABLE: TableDefinition<&str, &str> = TableDefinition::new("mint_quotes");
const MELT_QUOTES_TABLE: TableDefinition<&str, &str> = TableDefinition::new("melt_quotes");
const PENDING_PROOFS_TABLE: TableDefinition<[u8; 33], &str> =
TableDefinition::new("pending_proofs");
const SPENT_PROOFS_TABLE: TableDefinition<[u8; 33], &str> = TableDefinition::new("spent_proofs");
const PROOFS_TABLE: TableDefinition<[u8; 33], &str> = TableDefinition::new("proofs");
const PROOFS_STATE_TABLE: TableDefinition<[u8; 33], &str> = TableDefinition::new("proofs_state");
const CONFIG_TABLE: TableDefinition<&str, &str> = TableDefinition::new("config");
// Key is hex blinded_message B_ value is blinded_signature
const BLINDED_SIGNATURES: TableDefinition<[u8; 33], &str> =
TableDefinition::new("blinded_signatures");
const DATABASE_VERSION: u32 = 2;
const DATABASE_VERSION: u32 = 3;
/// Mint Redbdatabase
#[derive(Debug, Clone)]
@@ -78,6 +78,10 @@ impl MintRedbDatabase {
current_file_version = migrate_01_to_02(Arc::clone(&db))?;
}
if current_file_version == 2 {
current_file_version = migrate_02_to_03(Arc::clone(&db))?;
}
if current_file_version != DATABASE_VERSION {
tracing::warn!(
"Database upgrade did not complete at {} current is {}",
@@ -109,8 +113,8 @@ impl MintRedbDatabase {
let _ = write_txn.open_table(KEYSETS_TABLE)?;
let _ = write_txn.open_table(MINT_QUOTES_TABLE)?;
let _ = write_txn.open_table(MELT_QUOTES_TABLE)?;
let _ = write_txn.open_table(PENDING_PROOFS_TABLE)?;
let _ = write_txn.open_table(SPENT_PROOFS_TABLE)?;
let _ = write_txn.open_table(PROOFS_TABLE)?;
let _ = write_txn.open_table(PROOFS_STATE_TABLE)?;
let _ = write_txn.open_table(BLINDED_SIGNATURES)?;
table.insert("db_version", DATABASE_VERSION.to_string().as_str())?;
@@ -494,15 +498,13 @@ impl MintDatabase for MintRedbDatabase {
Ok(())
}
async fn add_spent_proofs(&self, proofs: Vec<Proof>) -> Result<(), Self::Err> {
async fn add_proofs(&self, proofs: Proofs) -> Result<(), Self::Err> {
let db = self.db.lock().await;
let write_txn = db.begin_write().map_err(Error::from)?;
{
let mut table = write_txn
.open_table(SPENT_PROOFS_TABLE)
.map_err(Error::from)?;
let mut table = write_txn.open_table(PROOFS_TABLE).map_err(Error::from)?;
for proof in proofs {
let y: PublicKey = hash_to_curve(&proof.secret.to_bytes()).map_err(Error::from)?;
table
@@ -518,15 +520,10 @@ impl MintDatabase for MintRedbDatabase {
Ok(())
}
async fn get_spent_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 db = self.db.lock().await;
let read_txn = db.begin_read().map_err(Error::from)?;
let table = read_txn
.open_table(SPENT_PROOFS_TABLE)
.map_err(Error::from)?;
let table = read_txn.open_table(PROOFS_TABLE).map_err(Error::from)?;
let mut proofs = Vec::with_capacity(ys.len());
@@ -542,70 +539,55 @@ impl MintDatabase for MintRedbDatabase {
Ok(proofs)
}
async fn add_pending_proofs(&self, proofs: Vec<Proof>) -> Result<(), Self::Err> {
let db = self.db.lock().await;
let write_txn = db.begin_write().map_err(Error::from)?;
{
let mut table = write_txn
.open_table(PENDING_PROOFS_TABLE)
.map_err(Error::from)?;
for proof in proofs {
table
.insert(
hash_to_curve(&proof.secret.to_bytes())?.to_bytes(),
serde_json::to_string(&proof).map_err(Error::from)?.as_str(),
)
.map_err(Error::from)?;
}
}
write_txn.commit().map_err(Error::from)?;
Ok(())
}
async fn get_pending_proofs_by_ys(
&self,
ys: &[PublicKey],
) -> Result<Vec<Option<Proof>>, Self::Err> {
async fn get_proofs_states(&self, ys: &[PublicKey]) -> Result<Vec<Option<State>>, Self::Err> {
let db = self.db.lock().await;
let read_txn = db.begin_read().map_err(Error::from)?;
let table = read_txn
.open_table(PENDING_PROOFS_TABLE)
.open_table(PROOFS_STATE_TABLE)
.map_err(Error::from)?;
let mut proofs = Vec::with_capacity(ys.len());
let mut states = Vec::with_capacity(ys.len());
for y in ys {
match table.get(y.to_bytes()).map_err(Error::from)? {
Some(proof) => proofs.push(Some(
serde_json::from_str(proof.value()).map_err(Error::from)?,
Some(state) => states.push(Some(
serde_json::from_str(state.value()).map_err(Error::from)?,
)),
None => proofs.push(None),
None => states.push(None),
}
}
Ok(proofs)
Ok(states)
}
async fn remove_pending_proofs(&self, secrets: Vec<&Secret>) -> Result<(), Self::Err> {
async fn update_proofs_states(
&self,
ys: &[PublicKey],
proofs_state: State,
) -> Result<Vec<Option<State>>, Self::Err> {
let db = self.db.lock().await;
let write_txn = db.begin_write().map_err(Error::from)?;
let mut table = write_txn
.open_table(PROOFS_STATE_TABLE)
.map_err(Error::from)?;
{
let mut table = write_txn
.open_table(PENDING_PROOFS_TABLE)
.map_err(Error::from)?;
for secret in secrets {
let secret_hash = hash_to_curve(&secret.to_bytes()).map_err(Error::from)?;
table.remove(secret_hash.to_bytes()).map_err(Error::from)?;
let mut states = Vec::with_capacity(ys.len());
let state_str = serde_json::to_string(&proofs_state).map_err(Error::from)?;
for y in ys {
match table
.insert(y.to_bytes(), state_str.as_str())
.map_err(Error::from)?
{
Some(state) => states.push(Some(
serde_json::from_str(state.value()).map_err(Error::from)?,
)),
None => states.push(None),
}
}
write_txn.commit().map_err(Error::from)?;
Ok(())
Ok(states)
}
async fn add_blind_signatures(