mirror of
https://github.com/aljazceru/cdk.git
synced 2025-12-19 05:35:18 +01:00
Keyset counter (#950)
* feat: refresh keysets * fix(cdk): resolve keyset counter skipping index 0 in deterministic secret generation - Modified Database::get_keyset_counter to return u32 instead of Option<u32> - Added database migrations to increment existing keyset counters by 1 - Removed counter increment logic from wallet operations to use actual counter value - Ensures deterministic secret generation starts from index 0 instead of skipping it
This commit is contained in:
@@ -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<u32>` 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]).
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<Option<u32>, Self::Err>;
|
||||
async fn get_keyset_counter(&self, keyset_id: &Id) -> Result<u32, Self::Err>;
|
||||
|
||||
/// Add transaction to storage
|
||||
async fn add_transaction(&self, transaction: Transaction) -> Result<(), Self::Err>;
|
||||
|
||||
@@ -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};
|
||||
|
||||
// <Mint_url, Info>
|
||||
const MINTS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("mints_table");
|
||||
@@ -152,3 +152,51 @@ fn migrate_trim_mint_urls_01_to_02(db: Arc<Database>) -> Result<(), Error> {
|
||||
migrate_mint_keyset_table_01_to_02(Arc::clone(&db))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn migrate_03_to_04(db: Arc<Database>) -> Result<u32, Error> {
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -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<u32, &str> = 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<Option<u32>, Self::Err> {
|
||||
async fn get_keyset_counter(&self, keyset_id: &Id) -> Result<u32, Self::Err> {
|
||||
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))]
|
||||
|
||||
@@ -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"#)),
|
||||
];
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
-- Increment keyset counter by 1 where counter > 0
|
||||
UPDATE keyset SET counter = counter + 1 WHERE counter > 0;
|
||||
@@ -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<Option<u32>, Self::Err> {
|
||||
async fn get_keyset_counter(&self, keyset_id: &Id) -> Result<u32, Self::Err> {
|
||||
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))]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user