migrations.rs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. //! Wallet Migrations
  2. use std::collections::HashSet;
  3. use std::ops::Deref;
  4. use std::str::FromStr;
  5. use std::sync::Arc;
  6. use cdk_common::mint_url::MintUrl;
  7. use cdk_common::Id;
  8. use redb::{
  9. Database, MultimapTableDefinition, ReadableMultimapTable, ReadableTable, TableDefinition,
  10. };
  11. use super::Error;
  12. use crate::wallet::{KEYSETS_TABLE, KEYSET_COUNTER, KEYSET_U32_MAPPING, MINT_KEYS_TABLE};
  13. // <Mint_url, Info>
  14. const MINTS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("mints_table");
  15. // <Mint_Url, Keyset_id>
  16. const MINT_KEYSETS_TABLE: MultimapTableDefinition<&str, &[u8]> =
  17. MultimapTableDefinition::new("mint_keysets");
  18. pub(crate) fn migrate_02_to_03(db: Arc<Database>) -> Result<u32, Error> {
  19. let write_txn = db.begin_write().map_err(Error::from)?;
  20. let mut duplicate = false;
  21. {
  22. let table = write_txn.open_table(MINT_KEYS_TABLE).map_err(Error::from)?;
  23. let ids: Vec<Id> = table
  24. .iter()
  25. .map_err(Error::from)?
  26. .flatten()
  27. .flat_map(|(id, _)| Id::from_str(id.value()))
  28. .collect();
  29. let mut table = write_txn
  30. .open_table(KEYSET_U32_MAPPING)
  31. .map_err(Error::from)?;
  32. // Also process existing keysets
  33. let keysets_table = write_txn.open_table(KEYSETS_TABLE).map_err(Error::from)?;
  34. let keyset_ids: Vec<Id> = keysets_table
  35. .iter()
  36. .map_err(Error::from)?
  37. .flatten()
  38. .flat_map(|(id_bytes, _)| Id::from_bytes(id_bytes.value()))
  39. .collect();
  40. let ids: HashSet<Id> = ids.into_iter().chain(keyset_ids).collect();
  41. for id in ids {
  42. let t = table.insert(u32::from(id), id.to_string().as_str())?;
  43. tracing::info!("Adding u32 {} for keyset {}", u32::from(id), id.to_string());
  44. if t.is_some() {
  45. duplicate = true;
  46. }
  47. }
  48. }
  49. if duplicate {
  50. write_txn.abort()?;
  51. return Err(Error::Duplicate);
  52. }
  53. write_txn.commit()?;
  54. Ok(3)
  55. }
  56. pub fn migrate_01_to_02(db: Arc<Database>) -> Result<u32, Error> {
  57. migrate_trim_mint_urls_01_to_02(db)?;
  58. Ok(2)
  59. }
  60. fn migrate_mints_table_01_to_02(db: Arc<Database>) -> Result<(), Error> {
  61. let mints: Vec<(String, String)>;
  62. {
  63. let read_txn = db.begin_read().map_err(Error::from)?;
  64. let table = read_txn.open_table(MINTS_TABLE).map_err(Error::from)?;
  65. mints = table
  66. .iter()
  67. .map_err(Error::from)?
  68. .flatten()
  69. .map(|(mint_url, mint_info)| {
  70. (mint_url.value().to_string(), mint_info.value().to_string())
  71. })
  72. .collect();
  73. }
  74. let write_txn = db.begin_write()?;
  75. {
  76. let mut table = write_txn.open_table(MINTS_TABLE).map_err(Error::from)?;
  77. for (mint_url_str, info) in mints {
  78. let mint_url = MintUrl::from_str(&mint_url_str).map_err(Error::from)?;
  79. table.remove(mint_url_str.as_str())?;
  80. table.insert(mint_url.to_string().as_str(), info.as_str())?;
  81. }
  82. }
  83. write_txn.commit()?;
  84. Ok(())
  85. }
  86. fn migrate_mint_keyset_table_01_to_02(db: Arc<Database>) -> Result<(), Error> {
  87. let mut mints: Vec<(String, Vec<Vec<u8>>)> = vec![];
  88. {
  89. let read_txn = db.begin_read().map_err(Error::from)?;
  90. let table = read_txn
  91. .open_multimap_table(MINT_KEYSETS_TABLE)
  92. .map_err(Error::from)?;
  93. let mint_keysets_range = table.iter().map_err(Error::from)?;
  94. for (url, keysets) in mint_keysets_range.flatten() {
  95. let keysets: Vec<Vec<u8>> = keysets
  96. .into_iter()
  97. .flatten()
  98. .map(|k| k.value().to_vec())
  99. .collect();
  100. mints.push((url.value().to_string(), keysets));
  101. }
  102. }
  103. let write_txn = db.begin_write()?;
  104. {
  105. let mut table = write_txn
  106. .open_multimap_table(MINT_KEYSETS_TABLE)
  107. .map_err(Error::from)?;
  108. for (mint_url_str, keysets) in mints {
  109. let mint_url = MintUrl::from_str(&mint_url_str).map_err(Error::from)?;
  110. table.remove_all(mint_url_str.as_str())?;
  111. for keyset in keysets {
  112. table.insert(mint_url.to_string().as_str(), keyset.deref())?;
  113. }
  114. }
  115. }
  116. write_txn.commit()?;
  117. Ok(())
  118. }
  119. fn migrate_trim_mint_urls_01_to_02(db: Arc<Database>) -> Result<(), Error> {
  120. migrate_mints_table_01_to_02(Arc::clone(&db))?;
  121. migrate_mint_keyset_table_01_to_02(Arc::clone(&db))?;
  122. Ok(())
  123. }
  124. pub(crate) fn migrate_03_to_04(db: Arc<Database>) -> Result<u32, Error> {
  125. let write_txn = db.begin_write().map_err(Error::from)?;
  126. // Get all existing keyset IDs from the KEYSET_COUNTER table that have a counter > 0
  127. let keyset_ids_to_increment: Vec<(String, u32)>;
  128. {
  129. let table = write_txn.open_table(KEYSET_COUNTER).map_err(Error::from)?;
  130. keyset_ids_to_increment = table
  131. .iter()
  132. .map_err(Error::from)?
  133. .flatten()
  134. .filter_map(|(keyset_id, counter)| {
  135. let counter_value = counter.value();
  136. // Only include keysets where counter > 0
  137. if counter_value > 0 {
  138. Some((keyset_id.value().to_string(), counter_value))
  139. } else {
  140. None
  141. }
  142. })
  143. .collect();
  144. }
  145. // Increment counter by 1 for all keysets where counter > 0
  146. {
  147. let mut table = write_txn.open_table(KEYSET_COUNTER).map_err(Error::from)?;
  148. for (keyset_id, current_counter) in keyset_ids_to_increment {
  149. let new_counter = current_counter + 1;
  150. table
  151. .insert(keyset_id.as_str(), new_counter)
  152. .map_err(Error::from)?;
  153. tracing::info!(
  154. "Incremented counter for keyset {} from {} to {}",
  155. keyset_id,
  156. current_counter,
  157. new_counter
  158. );
  159. }
  160. }
  161. write_txn.commit()?;
  162. Ok(4)
  163. }