mirror of
https://github.com/aljazceru/cdk.git
synced 2025-12-23 23:55:01 +01:00
feat: add keyset u32 mapping migration (#926)
* feat: add keyset u32 mapping migration and duplicate handling - Add new database migration (version 3) to include u32 representation for keysets - Implement migration for both redb and SQL databases - Add duplicate detection and handling for keyset entries - Create unique index constraint for keyset_u32 column in SQL - Update keyset storage to include u32 identifiers - Handle backwards compatibility for existing databases * chore: clippy * refactor(cashu): simplify keyset ID verification logic - Consolidate match expression into a single expression - Use direct comparison with ensure_cdk macro - Improve readability of keyset ID validation * refactor(cdk): rename `fetch_keyset_keys` to `load_keyset_keys` for clarity - Renamed `fetch_keyset_keys` to `load_keyset_keys` across multiple modules to better reflect its behavior of loading keys from local storage or fetching from mint when missing. - Added debug logging to indicate when keys are being fetched from the mint. - Simplified key loading logic in `update_mint_keysets` by removing redundant existence checks. * chore: remove unused vec
This commit is contained in:
@@ -19,4 +19,5 @@ pub static MIGRATIONS: &[(&str, &str, &str)] = &[
|
||||
("sqlite", "20250401120000_add_transactions_table.sql", include_str!(r#"./migrations/sqlite/20250401120000_add_transactions_table.sql"#)),
|
||||
("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"#)),
|
||||
];
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
-- Add u32 representation column to key table with unique constraint
|
||||
ALTER TABLE key ADD COLUMN keyset_u32 INTEGER;
|
||||
|
||||
-- Add unique constraint on the new column
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS keyset_u32_unique ON key(keyset_u32);
|
||||
|
||||
-- Add u32 representation column to keyset table with unique constraint
|
||||
ALTER TABLE keyset ADD COLUMN keyset_u32 INTEGER;
|
||||
|
||||
-- Add unique constraint on the new column
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS keyset_u32_unique_keyset ON keyset(keyset_u32);
|
||||
@@ -53,6 +53,74 @@ where
|
||||
/// Migrate [`WalletSqliteDatabase`]
|
||||
async fn migrate(conn: &DB) -> Result<(), Error> {
|
||||
migrate(conn, DB::name(), migrations::MIGRATIONS).await?;
|
||||
// Update any existing keys with missing keyset_u32 values
|
||||
Self::add_keyset_u32(conn).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn add_keyset_u32(conn: &DB) -> Result<(), Error> {
|
||||
// First get the keysets where keyset_u32 on key is null
|
||||
let keys_without_u32: Vec<Vec<Column>> = query(
|
||||
r#"
|
||||
SELECT
|
||||
id
|
||||
FROM key
|
||||
WHERE keyset_u32 IS NULL
|
||||
"#,
|
||||
)?
|
||||
.fetch_all(conn)
|
||||
.await?;
|
||||
|
||||
for id in keys_without_u32 {
|
||||
let id = column_as_string!(id.first().unwrap());
|
||||
|
||||
if let Ok(id) = Id::from_str(&id) {
|
||||
query(
|
||||
r#"
|
||||
UPDATE
|
||||
key
|
||||
SET keyset_u32 = :u32_keyset
|
||||
WHERE id = :keyset_id
|
||||
"#,
|
||||
)?
|
||||
.bind("u32_keyset", u32::from(id))
|
||||
.bind("keyset_id", id.to_string())
|
||||
.execute(conn)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
// Also update keysets where keyset_u32 is null
|
||||
let keysets_without_u32: Vec<Vec<Column>> = query(
|
||||
r#"
|
||||
SELECT
|
||||
id
|
||||
FROM keyset
|
||||
WHERE keyset_u32 IS NULL
|
||||
"#,
|
||||
)?
|
||||
.fetch_all(conn)
|
||||
.await?;
|
||||
|
||||
for id in keysets_without_u32 {
|
||||
let id = column_as_string!(id.first().unwrap());
|
||||
|
||||
if let Ok(id) = Id::from_str(&id) {
|
||||
query(
|
||||
r#"
|
||||
UPDATE
|
||||
keyset
|
||||
SET keyset_u32 = :u32_keyset
|
||||
WHERE id = :keyset_id
|
||||
"#,
|
||||
)?
|
||||
.bind("u32_keyset", u32::from(id))
|
||||
.bind("keyset_id", id.to_string())
|
||||
.execute(conn)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -301,15 +369,12 @@ ON CONFLICT(mint_url) DO UPDATE SET
|
||||
query(
|
||||
r#"
|
||||
INSERT INTO keyset
|
||||
(mint_url, id, unit, active, input_fee_ppk, final_expiry)
|
||||
(mint_url, id, unit, active, input_fee_ppk, final_expiry, keyset_u32)
|
||||
VALUES
|
||||
(:mint_url, :id, :unit, :active, :input_fee_ppk, :final_expiry)
|
||||
(:mint_url, :id, :unit, :active, :input_fee_ppk, :final_expiry, :keyset_u32)
|
||||
ON CONFLICT(id) DO UPDATE SET
|
||||
mint_url = excluded.mint_url,
|
||||
unit = excluded.unit,
|
||||
active = excluded.active,
|
||||
input_fee_ppk = excluded.input_fee_ppk,
|
||||
final_expiry = excluded.final_expiry;
|
||||
input_fee_ppk = excluded.input_fee_ppk
|
||||
"#,
|
||||
)?
|
||||
.bind("mint_url", mint_url.to_string())
|
||||
@@ -318,6 +383,7 @@ ON CONFLICT(mint_url) DO UPDATE SET
|
||||
.bind("active", keyset.active)
|
||||
.bind("input_fee_ppk", keyset.input_fee_ppk as i64)
|
||||
.bind("final_expiry", keyset.final_expiry.map(|v| v as i64))
|
||||
.bind("keyset_u32", u32::from(keyset.id))
|
||||
.execute(&self.db)
|
||||
.await?;
|
||||
}
|
||||
@@ -554,11 +620,9 @@ ON CONFLICT(id) DO UPDATE SET
|
||||
query(
|
||||
r#"
|
||||
INSERT INTO key
|
||||
(id, keys)
|
||||
(id, keys, keyset_u32)
|
||||
VALUES
|
||||
(:id, :keys)
|
||||
ON CONFLICT(id) DO UPDATE SET
|
||||
keys = excluded.keys
|
||||
(:id, :keys, :keyset_u32)
|
||||
"#,
|
||||
)?
|
||||
.bind("id", keyset.id.to_string())
|
||||
@@ -566,6 +630,7 @@ ON CONFLICT(id) DO UPDATE SET
|
||||
"keys",
|
||||
serde_json::to_string(&keyset.keys).map_err(Error::from)?,
|
||||
)
|
||||
.bind("keyset_u32", u32::from(keyset.id))
|
||||
.execute(&self.db)
|
||||
.await?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user