| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- //! Keys database tests
- use std::str::FromStr;
- use bitcoin::bip32::DerivationPath;
- use cashu::{CurrencyUnit, Id};
- use crate::database::mint::{Database, Error, KeysDatabase};
- use crate::mint::MintKeySetInfo;
- /// Generate standard keyset amounts as powers of 2
- fn standard_keyset_amounts(max_order: u32) -> Vec<u64> {
- (0..max_order).map(|n| 2u64.pow(n)).collect()
- }
- /// Test adding and retrieving keyset info
- pub async fn add_and_get_keyset_info<DB>(db: DB)
- where
- DB: Database<Error> + KeysDatabase<Err = 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: DerivationPath::from_str("m/0'/0'/0'").unwrap(),
- derivation_path_index: Some(0),
- input_fee_ppk: 0,
- amounts: standard_keyset_amounts(32),
- };
- // Add keyset info
- let mut tx = KeysDatabase::begin_transaction(&db).await.unwrap();
- tx.add_keyset_info(keyset_info.clone()).await.unwrap();
- tx.commit().await.unwrap();
- // Retrieve keyset info
- let retrieved = db.get_keyset_info(&keyset_id).await.unwrap();
- assert!(retrieved.is_some());
- let retrieved = retrieved.unwrap();
- assert_eq!(retrieved.id, keyset_info.id);
- assert_eq!(retrieved.unit, keyset_info.unit);
- assert_eq!(retrieved.active, keyset_info.active);
- assert_eq!(retrieved.amounts, keyset_info.amounts);
- }
- /// Test adding duplicate keyset info is idempotent
- pub async fn add_duplicate_keyset_info<DB>(db: DB)
- where
- DB: Database<Error> + KeysDatabase<Err = 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: DerivationPath::from_str("m/0'/0'/0'").unwrap(),
- derivation_path_index: Some(0),
- input_fee_ppk: 0,
- amounts: standard_keyset_amounts(32),
- };
- // Add keyset info first time
- let mut tx = KeysDatabase::begin_transaction(&db).await.unwrap();
- tx.add_keyset_info(keyset_info.clone()).await.unwrap();
- tx.commit().await.unwrap();
- // Add the same keyset info again - this may succeed (idempotent) or fail
- // Both behaviors are acceptable
- let mut tx = KeysDatabase::begin_transaction(&db).await.unwrap();
- let result = tx.add_keyset_info(keyset_info).await;
- assert!(result.is_ok());
- tx.commit().await.unwrap();
- // Verify keyset still exists
- let retrieved = db.get_keyset_info(&keyset_id).await.unwrap();
- assert!(retrieved.is_some());
- }
- /// Test getting all keyset infos
- pub async fn get_all_keyset_infos<DB>(db: DB)
- where
- DB: Database<Error> + KeysDatabase<Err = Error>,
- {
- let keyset_id1 = Id::from_str("00916bbf7ef91a36").unwrap();
- let keyset_info1 = MintKeySetInfo {
- id: keyset_id1,
- unit: CurrencyUnit::Sat,
- active: true,
- valid_from: 0,
- final_expiry: None,
- derivation_path: DerivationPath::from_str("m/0'/0'/0'").unwrap(),
- derivation_path_index: Some(0),
- input_fee_ppk: 0,
- amounts: standard_keyset_amounts(32),
- };
- let keyset_id2 = Id::from_str("00916bbf7ef91a37").unwrap();
- let keyset_info2 = MintKeySetInfo {
- id: keyset_id2,
- unit: CurrencyUnit::Sat,
- active: false,
- valid_from: 0,
- final_expiry: None,
- derivation_path: DerivationPath::from_str("m/0'/0'/1'").unwrap(),
- derivation_path_index: Some(1),
- input_fee_ppk: 0,
- amounts: standard_keyset_amounts(32),
- };
- // Add keyset infos
- let mut tx = KeysDatabase::begin_transaction(&db).await.unwrap();
- tx.add_keyset_info(keyset_info1.clone()).await.unwrap();
- tx.add_keyset_info(keyset_info2.clone()).await.unwrap();
- tx.commit().await.unwrap();
- // Get all keyset infos
- let all_keysets = db.get_keyset_infos().await.unwrap();
- assert!(all_keysets.len() >= 2);
- assert!(all_keysets.iter().any(|k| k.id == keyset_id1));
- assert!(all_keysets.iter().any(|k| k.id == keyset_id2));
- }
- /// Test setting and getting active keyset
- pub async fn set_and_get_active_keyset<DB>(db: DB)
- where
- DB: Database<Error> + KeysDatabase<Err = 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: DerivationPath::from_str("m/0'/0'/0'").unwrap(),
- derivation_path_index: Some(0),
- input_fee_ppk: 0,
- amounts: standard_keyset_amounts(32),
- };
- // Add keyset info
- let mut tx = KeysDatabase::begin_transaction(&db).await.unwrap();
- tx.add_keyset_info(keyset_info.clone()).await.unwrap();
- tx.set_active_keyset(CurrencyUnit::Sat, keyset_id)
- .await
- .unwrap();
- tx.commit().await.unwrap();
- // Get active keyset
- let active_id = db.get_active_keyset_id(&CurrencyUnit::Sat).await.unwrap();
- assert!(active_id.is_some());
- assert_eq!(active_id.unwrap(), keyset_id);
- }
- /// Test getting all active keysets
- pub async fn get_all_active_keysets<DB>(db: DB)
- where
- DB: Database<Error> + KeysDatabase<Err = Error>,
- {
- let keyset_id_sat = Id::from_str("00916bbf7ef91a36").unwrap();
- let keyset_info_sat = MintKeySetInfo {
- id: keyset_id_sat,
- unit: CurrencyUnit::Sat,
- active: true,
- valid_from: 0,
- final_expiry: None,
- derivation_path: DerivationPath::from_str("m/0'/0'/0'").unwrap(),
- derivation_path_index: Some(0),
- input_fee_ppk: 0,
- amounts: standard_keyset_amounts(32),
- };
- let keyset_id_usd = Id::from_str("00916bbf7ef91a37").unwrap();
- let keyset_info_usd = MintKeySetInfo {
- id: keyset_id_usd,
- unit: CurrencyUnit::Usd,
- active: true,
- valid_from: 0,
- final_expiry: None,
- derivation_path: DerivationPath::from_str("m/0'/0'/1'").unwrap(),
- derivation_path_index: Some(1),
- input_fee_ppk: 0,
- amounts: standard_keyset_amounts(32),
- };
- // Add keyset infos and set as active
- let mut tx = KeysDatabase::begin_transaction(&db).await.unwrap();
- tx.add_keyset_info(keyset_info_sat.clone()).await.unwrap();
- tx.add_keyset_info(keyset_info_usd.clone()).await.unwrap();
- tx.set_active_keyset(CurrencyUnit::Sat, keyset_id_sat)
- .await
- .unwrap();
- tx.set_active_keyset(CurrencyUnit::Usd, keyset_id_usd)
- .await
- .unwrap();
- tx.commit().await.unwrap();
- // Get all active keysets
- let active_keysets = db.get_active_keysets().await.unwrap();
- assert!(active_keysets.len() >= 2);
- assert_eq!(active_keysets.get(&CurrencyUnit::Sat), Some(&keyset_id_sat));
- assert_eq!(active_keysets.get(&CurrencyUnit::Usd), Some(&keyset_id_usd));
- }
- /// Test updating active keyset
- pub async fn update_active_keyset<DB>(db: DB)
- where
- DB: Database<Error> + KeysDatabase<Err = Error>,
- {
- let keyset_id1 = Id::from_str("00916bbf7ef91a36").unwrap();
- let keyset_info1 = MintKeySetInfo {
- id: keyset_id1,
- unit: CurrencyUnit::Sat,
- active: true,
- valid_from: 0,
- final_expiry: None,
- derivation_path: DerivationPath::from_str("m/0'/0'/0'").unwrap(),
- derivation_path_index: Some(0),
- input_fee_ppk: 0,
- amounts: standard_keyset_amounts(32),
- };
- let keyset_id2 = Id::from_str("00916bbf7ef91a37").unwrap();
- let keyset_info2 = MintKeySetInfo {
- id: keyset_id2,
- unit: CurrencyUnit::Sat,
- active: false,
- valid_from: 0,
- final_expiry: None,
- derivation_path: DerivationPath::from_str("m/0'/0'/1'").unwrap(),
- derivation_path_index: Some(1),
- input_fee_ppk: 0,
- amounts: standard_keyset_amounts(32),
- };
- // Add both keysets and set first as active
- let mut tx = KeysDatabase::begin_transaction(&db).await.unwrap();
- tx.add_keyset_info(keyset_info1.clone()).await.unwrap();
- tx.add_keyset_info(keyset_info2.clone()).await.unwrap();
- tx.set_active_keyset(CurrencyUnit::Sat, keyset_id1)
- .await
- .unwrap();
- tx.commit().await.unwrap();
- // Verify first keyset is active
- let active_id = db.get_active_keyset_id(&CurrencyUnit::Sat).await.unwrap();
- assert_eq!(active_id, Some(keyset_id1));
- // Update to second keyset
- let mut tx = KeysDatabase::begin_transaction(&db).await.unwrap();
- tx.set_active_keyset(CurrencyUnit::Sat, keyset_id2)
- .await
- .unwrap();
- tx.commit().await.unwrap();
- // Verify second keyset is now active
- let active_id = db.get_active_keyset_id(&CurrencyUnit::Sat).await.unwrap();
- assert_eq!(active_id, Some(keyset_id2));
- }
- /// Test getting non-existent keyset info
- pub async fn get_nonexistent_keyset_info<DB>(db: DB)
- where
- DB: Database<Error> + KeysDatabase<Err = Error>,
- {
- let keyset_id = Id::from_str("00916bbf7ef91a36").unwrap();
- // Try to get non-existent keyset
- let retrieved = db.get_keyset_info(&keyset_id).await.unwrap();
- assert!(retrieved.is_none());
- }
- /// Test getting active keyset when none is set
- pub async fn get_active_keyset_when_none_set<DB>(db: DB)
- where
- DB: Database<Error> + KeysDatabase<Err = Error>,
- {
- // Try to get active keyset when none is set
- let active_id = db.get_active_keyset_id(&CurrencyUnit::Sat).await.unwrap();
- assert!(active_id.is_none());
- }
|