Files
cdk/crates/cdk-common/src/database/mint/test.rs
C 238b09d56a Split the database trait into read and transactions. (#826)
* Split the database trait into read and transactions.

The transaction traits will encapsulate all database changes and also expect
READ-and-lock operations to read and lock records from the database for
exclusive access, thereby avoiding race conditions.

The Transaction trait expects a `rollback` operation on Drop unless the
transaction has been committed.

* fix: melt quote duplicate error

This change stops a second melt quote from being created
if there is an existing valid melt quote for an invoice already.
If the first melt quote has expired then we allow for a new melt quote to be created.

---------

Co-authored-by: thesimplekid <tsk@thesimplekid.com>
2025-06-28 12:07:47 +01:00

94 lines
2.6 KiB
Rust

//! Macro with default tests
//!
//! This set is generic and checks the default and expected behaviour for a mint database
//! implementation
use std::str::FromStr;
use cashu::secret::Secret;
use cashu::{Amount, CurrencyUnit, SecretKey};
use super::*;
use crate::database;
use crate::mint::MintKeySetInfo;
#[inline]
async fn setup_keyset<DB>(db: &DB) -> Id
where
DB: KeysDatabase<Err = database::Error>,
{
let keyset_id = Id::from_str("00916bbf7ef91a36").unwrap();
let keyset_info = MintKeySetInfo {
id: keyset_id,
unit: CurrencyUnit::Sat,
active: true,
valid_from: 0,
final_expiry: None,
derivation_path: bitcoin::bip32::DerivationPath::from_str("m/0'/0'/0'").unwrap(),
derivation_path_index: Some(0),
max_order: 32,
input_fee_ppk: 0,
};
let mut writer = db.begin_transaction().await.expect("db.begin()");
writer.add_keyset_info(keyset_info).await.unwrap();
writer.commit().await.expect("commit()");
keyset_id
}
/// State transition test
pub async fn state_transition<DB>(db: DB)
where
DB: Database<database::Error> + KeysDatabase<Err = database::Error>,
{
let keyset_id = setup_keyset(&db).await;
let proofs = vec![
Proof {
amount: Amount::from(100),
keyset_id,
secret: Secret::generate(),
c: SecretKey::generate().public_key(),
witness: None,
dleq: None,
},
Proof {
amount: Amount::from(200),
keyset_id,
secret: Secret::generate(),
c: SecretKey::generate().public_key(),
witness: None,
dleq: None,
},
];
// Add proofs to database
let mut tx = Database::begin_transaction(&db).await.unwrap();
tx.add_proofs(proofs.clone(), None).await.unwrap();
// Mark one proof as `pending`
assert!(tx
.update_proofs_states(&[proofs[0].y().unwrap()], State::Pending)
.await
.is_ok());
// Attempt to select the `pending` proof, as `pending` again (which should fail)
assert!(tx
.update_proofs_states(&[proofs[0].y().unwrap()], State::Pending)
.await
.is_err());
tx.commit().await.unwrap();
}
/// Unit test that is expected to be passed for a correct database implementation
#[macro_export]
macro_rules! mint_db_test {
($make_db_fn:ident) => {
mint_db_test!(state_transition, $make_db_fn);
};
($name:ident, $make_db_fn:ident) => {
#[tokio::test]
async fn $name() {
cdk_common::database::mint::test::$name($make_db_fn().await).await;
}
};
}