diff --git a/CHANGELOG.md b/CHANGELOG.md index c03aa5be..ed171e15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,8 +18,11 @@ - cdk-integration-tests: New binary `start_fake_mint` for testing fake mint instances ([thesimplekid]). - cdk-integration-tests: New binary `start_regtest_mints` for testing regtest mints ([thesimplekid]). - cdk-integration-tests: Shared utilities module for common integration test functionality ([thesimplekid]). +- cdk-redb: Database migration to increment keyset counters by 1 for existing keysets with counter > 0 ([thesimplekid]). +- cdk-sql-common: Database migration to increment keyset counters by 1 for existing keysets with counter > 0 ([thesimplekid]). ### Changed +- cdk-common: Modified `Database::get_keyset_counter` trait method to return `u32` instead of `Option` for simpler keyset counter handling ([thesimplekid]). - cdk: Refactored wallet keyset management methods for better clarity and separation of concerns ([thesimplekid]). - cdk: Renamed `get_keyset_keys` to `fetch_keyset_keys` to indicate network operation ([thesimplekid]). - cdk: Renamed `get_active_mint_keyset` to `fetch_active_keyset` for consistency ([thesimplekid]). diff --git a/crates/cdk-cli/src/main.rs b/crates/cdk-cli/src/main.rs index 31caec4a..d85cc06b 100644 --- a/crates/cdk-cli/src/main.rs +++ b/crates/cdk-cli/src/main.rs @@ -211,7 +211,8 @@ async fn main() -> Result<()> { let wallet_clone = wallet.clone(); tokio::spawn(async move { - if let Err(err) = wallet_clone.get_mint_info().await { + // We refresh keysets, this internally gets mint info + if let Err(err) = wallet_clone.refresh_keysets().await { tracing::error!( "Could not get mint quote for {}, {}", wallet_clone.mint_url, diff --git a/crates/cdk-common/src/database/wallet.rs b/crates/cdk-common/src/database/wallet.rs index 074f0708..2e53139f 100644 --- a/crates/cdk-common/src/database/wallet.rs +++ b/crates/cdk-common/src/database/wallet.rs @@ -102,7 +102,7 @@ pub trait Database: Debug { /// Increment Keyset counter async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<(), Self::Err>; /// Get current Keyset counter - async fn get_keyset_counter(&self, keyset_id: &Id) -> Result, Self::Err>; + async fn get_keyset_counter(&self, keyset_id: &Id) -> Result; /// Add transaction to storage async fn add_transaction(&self, transaction: Transaction) -> Result<(), Self::Err>; diff --git a/crates/cdk-redb/src/wallet/migrations.rs b/crates/cdk-redb/src/wallet/migrations.rs index 56a59216..948e9ab1 100644 --- a/crates/cdk-redb/src/wallet/migrations.rs +++ b/crates/cdk-redb/src/wallet/migrations.rs @@ -11,7 +11,7 @@ use redb::{ }; use super::Error; -use crate::wallet::{KEYSETS_TABLE, KEYSET_U32_MAPPING, MINT_KEYS_TABLE}; +use crate::wallet::{KEYSETS_TABLE, KEYSET_COUNTER, KEYSET_U32_MAPPING, MINT_KEYS_TABLE}; // const MINTS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("mints_table"); @@ -152,3 +152,51 @@ fn migrate_trim_mint_urls_01_to_02(db: Arc) -> Result<(), Error> { migrate_mint_keyset_table_01_to_02(Arc::clone(&db))?; Ok(()) } + +pub(crate) fn migrate_03_to_04(db: Arc) -> Result { + let write_txn = db.begin_write().map_err(Error::from)?; + + // Get all existing keyset IDs from the KEYSET_COUNTER table that have a counter > 0 + let keyset_ids_to_increment: Vec<(String, u32)>; + { + let table = write_txn.open_table(KEYSET_COUNTER).map_err(Error::from)?; + + keyset_ids_to_increment = table + .iter() + .map_err(Error::from)? + .flatten() + .filter_map(|(keyset_id, counter)| { + let counter_value = counter.value(); + // Only include keysets where counter > 0 + if counter_value > 0 { + Some((keyset_id.value().to_string(), counter_value)) + } else { + None + } + }) + .collect(); + } + + // Increment counter by 1 for all keysets where counter > 0 + { + let mut table = write_txn.open_table(KEYSET_COUNTER).map_err(Error::from)?; + + for (keyset_id, current_counter) in keyset_ids_to_increment { + let new_counter = current_counter + 1; + table + .insert(keyset_id.as_str(), new_counter) + .map_err(Error::from)?; + + tracing::info!( + "Incremented counter for keyset {} from {} to {}", + keyset_id, + current_counter, + new_counter + ); + } + } + + write_txn.commit()?; + + Ok(4) +} diff --git a/crates/cdk-redb/src/wallet/mod.rs b/crates/cdk-redb/src/wallet/mod.rs index 95f6d180..fba2107e 100644 --- a/crates/cdk-redb/src/wallet/mod.rs +++ b/crates/cdk-redb/src/wallet/mod.rs @@ -21,7 +21,7 @@ use tracing::instrument; use super::error::Error; use crate::migrations::migrate_00_to_01; -use crate::wallet::migrations::{migrate_01_to_02, migrate_02_to_03}; +use crate::wallet::migrations::{migrate_01_to_02, migrate_02_to_03, migrate_03_to_04}; mod migrations; @@ -46,7 +46,7 @@ const TRANSACTIONS_TABLE: TableDefinition<&[u8], &str> = TableDefinition::new("t const KEYSET_U32_MAPPING: TableDefinition = TableDefinition::new("keyset_u32_mapping"); -const DATABASE_VERSION: u32 = 3; +const DATABASE_VERSION: u32 = 4; /// Wallet Redb Database #[derive(Debug, Clone)] @@ -96,6 +96,10 @@ impl WalletRedbDatabase { 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 { tracing::warn!( "Database upgrade did not complete at {} current is {}", @@ -786,7 +790,7 @@ impl WalletDatabase for WalletRedbDatabase { } #[instrument(skip(self), fields(keyset_id = %keyset_id))] - async fn get_keyset_counter(&self, keyset_id: &Id) -> Result, Self::Err> { + async fn get_keyset_counter(&self, keyset_id: &Id) -> Result { let read_txn = self.db.begin_read().map_err(Error::from)?; let table = read_txn.open_table(KEYSET_COUNTER).map_err(Error::from)?; @@ -794,7 +798,7 @@ impl WalletDatabase for WalletRedbDatabase { .get(keyset_id.to_string().as_str()) .map_err(Error::from)?; - Ok(counter.map(|c| c.value())) + Ok(counter.map_or(0, |c| c.value())) } #[instrument(skip(self))] diff --git a/crates/cdk-sql-common/src/wallet/migrations.rs b/crates/cdk-sql-common/src/wallet/migrations.rs index 8fb3e52f..842cbd5a 100644 --- a/crates/cdk-sql-common/src/wallet/migrations.rs +++ b/crates/cdk-sql-common/src/wallet/migrations.rs @@ -20,4 +20,5 @@ pub static MIGRATIONS: &[(&str, &str, &str)] = &[ ("sqlite", "20250616144830_add_keyset_expiry.sql", include_str!(r#"./migrations/sqlite/20250616144830_add_keyset_expiry.sql"#)), ("sqlite", "20250707093445_bolt12.sql", include_str!(r#"./migrations/sqlite/20250707093445_bolt12.sql"#)), ("sqlite", "20250729111701_keyset_v2_u32.sql", include_str!(r#"./migrations/sqlite/20250729111701_keyset_v2_u32.sql"#)), + ("sqlite", "20250812084621_keyset_plus_one.sql", include_str!(r#"./migrations/sqlite/20250812084621_keyset_plus_one.sql"#)), ]; diff --git a/crates/cdk-sql-common/src/wallet/migrations/sqlite/20250812084621_keyset_plus_one.sql b/crates/cdk-sql-common/src/wallet/migrations/sqlite/20250812084621_keyset_plus_one.sql new file mode 100644 index 00000000..bd980b66 --- /dev/null +++ b/crates/cdk-sql-common/src/wallet/migrations/sqlite/20250812084621_keyset_plus_one.sql @@ -0,0 +1,2 @@ +-- Increment keyset counter by 1 where counter > 0 +UPDATE keyset SET counter = counter + 1 WHERE counter > 0; diff --git a/crates/cdk-sql-common/src/wallet/mod.rs b/crates/cdk-sql-common/src/wallet/mod.rs index 6c7324ed..0d84ac9d 100644 --- a/crates/cdk-sql-common/src/wallet/mod.rs +++ b/crates/cdk-sql-common/src/wallet/mod.rs @@ -857,7 +857,7 @@ ON CONFLICT(id) DO UPDATE SET } #[instrument(skip(self), fields(keyset_id = %keyset_id))] - async fn get_keyset_counter(&self, keyset_id: &Id) -> Result, Self::Err> { + async fn get_keyset_counter(&self, keyset_id: &Id) -> Result { let conn = self.pool.get().map_err(|e| Error::Database(Box::new(e)))?; Ok(query( r#" @@ -873,7 +873,8 @@ ON CONFLICT(id) DO UPDATE SET .pluck(&*conn) .await? .map(|n| Ok::<_, Error>(column_as_number!(n))) - .transpose()?) + .transpose()? + .unwrap_or(0)) } #[instrument(skip(self))] diff --git a/crates/cdk/src/wallet/issue/issue_bolt11.rs b/crates/cdk/src/wallet/issue/issue_bolt11.rs index c83baa62..5749a73c 100644 --- a/crates/cdk/src/wallet/issue/issue_bolt11.rs +++ b/crates/cdk/src/wallet/issue/issue_bolt11.rs @@ -234,8 +234,6 @@ impl Wallet { .get_keyset_counter(&active_keyset_id) .await?; - let count = count.map_or(0, |c| c + 1); - let premint_secrets = match &spending_conditions { Some(spending_conditions) => PreMintSecrets::with_conditions( active_keyset_id, diff --git a/crates/cdk/src/wallet/issue/issue_bolt12.rs b/crates/cdk/src/wallet/issue/issue_bolt12.rs index fe2185b7..179e2292 100644 --- a/crates/cdk/src/wallet/issue/issue_bolt12.rs +++ b/crates/cdk/src/wallet/issue/issue_bolt12.rs @@ -112,8 +112,6 @@ impl Wallet { .get_keyset_counter(&active_keyset_id) .await?; - let count = count.map_or(0, |c| c + 1); - let amount = match amount { Some(amount) => amount, None => { diff --git a/crates/cdk/src/wallet/melt/melt_bolt11.rs b/crates/cdk/src/wallet/melt/melt_bolt11.rs index c1a68482..0cc6657e 100644 --- a/crates/cdk/src/wallet/melt/melt_bolt11.rs +++ b/crates/cdk/src/wallet/melt/melt_bolt11.rs @@ -153,8 +153,6 @@ impl Wallet { .get_keyset_counter(&active_keyset_id) .await?; - let count = count.map_or(0, |c| c + 1); - let premint_secrets = PreMintSecrets::from_seed_blank( active_keyset_id, count, diff --git a/crates/cdk/src/wallet/swap.rs b/crates/cdk/src/wallet/swap.rs index 3d404815..fcb84d87 100644 --- a/crates/cdk/src/wallet/swap.rs +++ b/crates/cdk/src/wallet/swap.rs @@ -248,13 +248,11 @@ impl Wallet { let derived_secret_count; - let count = self + let mut count = self .localstore .get_keyset_counter(&active_keyset_id) .await?; - let mut count = count.map_or(0, |c| c + 1); - let (mut desired_messages, change_messages) = match spending_conditions { Some(conditions) => { let change_premint_secrets = PreMintSecrets::from_seed(