mod.rs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  1. //! Redb Wallet
  2. use std::cmp::Ordering;
  3. use std::collections::HashMap;
  4. use std::path::Path;
  5. use std::str::FromStr;
  6. use std::sync::Arc;
  7. use async_trait::async_trait;
  8. use cdk_common::common::ProofInfo;
  9. use cdk_common::database::WalletDatabase;
  10. use cdk_common::mint_url::MintUrl;
  11. use cdk_common::util::unix_time;
  12. use cdk_common::wallet::{self, MintQuote, Transaction, TransactionDirection, TransactionId};
  13. use cdk_common::{
  14. database, CurrencyUnit, Id, KeySet, KeySetInfo, Keys, MintInfo, PublicKey, SpendingConditions,
  15. State,
  16. };
  17. use redb::{Database, MultimapTableDefinition, ReadableTable, TableDefinition};
  18. use tracing::instrument;
  19. use super::error::Error;
  20. use crate::migrations::migrate_00_to_01;
  21. use crate::wallet::migrations::{migrate_01_to_02, migrate_02_to_03, migrate_03_to_04};
  22. mod migrations;
  23. // <Mint_url, Info>
  24. const MINTS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("mints_table");
  25. // <Mint_Url, Keyset_id>
  26. const MINT_KEYSETS_TABLE: MultimapTableDefinition<&str, &[u8]> =
  27. MultimapTableDefinition::new("mint_keysets");
  28. // <Keyset_id, KeysetInfo>
  29. const KEYSETS_TABLE: TableDefinition<&[u8], &str> = TableDefinition::new("keysets");
  30. // <Quote_id, quote>
  31. const MINT_QUOTES_TABLE: TableDefinition<&str, &str> = TableDefinition::new("mint_quotes");
  32. // <Quote_id, quote>
  33. const MELT_QUOTES_TABLE: TableDefinition<&str, &str> = TableDefinition::new("melt_quotes");
  34. const MINT_KEYS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("mint_keys");
  35. // <Y, Proof Info>
  36. const PROOFS_TABLE: TableDefinition<&[u8], &str> = TableDefinition::new("proofs");
  37. const CONFIG_TABLE: TableDefinition<&str, &str> = TableDefinition::new("config");
  38. const KEYSET_COUNTER: TableDefinition<&str, u32> = TableDefinition::new("keyset_counter");
  39. // <Transaction_id, Transaction>
  40. const TRANSACTIONS_TABLE: TableDefinition<&[u8], &str> = TableDefinition::new("transactions");
  41. const KEYSET_U32_MAPPING: TableDefinition<u32, &str> = TableDefinition::new("keyset_u32_mapping");
  42. const DATABASE_VERSION: u32 = 4;
  43. /// Wallet Redb Database
  44. #[derive(Debug, Clone)]
  45. pub struct WalletRedbDatabase {
  46. db: Arc<Database>,
  47. }
  48. impl WalletRedbDatabase {
  49. /// Create new [`WalletRedbDatabase`]
  50. pub fn new(path: &Path) -> Result<Self, Error> {
  51. {
  52. let db = Arc::new(Database::create(path)?);
  53. let db_version: Option<String>;
  54. {
  55. // Check database version
  56. let read_txn = db.begin_read()?;
  57. let table = read_txn.open_table(CONFIG_TABLE);
  58. db_version = match table {
  59. Ok(table) => table.get("db_version")?.map(|v| v.value().to_string()),
  60. Err(_) => None,
  61. };
  62. }
  63. match db_version {
  64. Some(db_version) => {
  65. let mut current_file_version = u32::from_str(&db_version)?;
  66. tracing::info!("Current file version {}", current_file_version);
  67. match current_file_version.cmp(&DATABASE_VERSION) {
  68. Ordering::Less => {
  69. tracing::info!(
  70. "Database needs to be upgraded at {} current is {}",
  71. current_file_version,
  72. DATABASE_VERSION
  73. );
  74. if current_file_version == 0 {
  75. current_file_version = migrate_00_to_01(Arc::clone(&db))?;
  76. }
  77. if current_file_version == 1 {
  78. current_file_version = migrate_01_to_02(Arc::clone(&db))?;
  79. }
  80. if current_file_version == 2 {
  81. current_file_version = migrate_02_to_03(Arc::clone(&db))?;
  82. }
  83. if current_file_version == 3 {
  84. current_file_version = migrate_03_to_04(Arc::clone(&db))?;
  85. }
  86. if current_file_version != DATABASE_VERSION {
  87. tracing::warn!(
  88. "Database upgrade did not complete at {} current is {}",
  89. current_file_version,
  90. DATABASE_VERSION
  91. );
  92. return Err(Error::UnknownDatabaseVersion);
  93. }
  94. let write_txn = db.begin_write()?;
  95. {
  96. let mut table = write_txn.open_table(CONFIG_TABLE)?;
  97. table
  98. .insert("db_version", DATABASE_VERSION.to_string().as_str())?;
  99. }
  100. write_txn.commit()?;
  101. }
  102. Ordering::Equal => {
  103. tracing::info!("Database is at current version {}", DATABASE_VERSION);
  104. }
  105. Ordering::Greater => {
  106. tracing::warn!(
  107. "Database upgrade did not complete at {} current is {}",
  108. current_file_version,
  109. DATABASE_VERSION
  110. );
  111. return Err(Error::UnknownDatabaseVersion);
  112. }
  113. }
  114. }
  115. None => {
  116. let write_txn = db.begin_write()?;
  117. {
  118. let mut table = write_txn.open_table(CONFIG_TABLE)?;
  119. // Open all tables to init a new db
  120. let _ = write_txn.open_table(MINTS_TABLE)?;
  121. let _ = write_txn.open_multimap_table(MINT_KEYSETS_TABLE)?;
  122. let _ = write_txn.open_table(KEYSETS_TABLE)?;
  123. let _ = write_txn.open_table(MINT_QUOTES_TABLE)?;
  124. let _ = write_txn.open_table(MELT_QUOTES_TABLE)?;
  125. let _ = write_txn.open_table(MINT_KEYS_TABLE)?;
  126. let _ = write_txn.open_table(PROOFS_TABLE)?;
  127. let _ = write_txn.open_table(KEYSET_COUNTER)?;
  128. let _ = write_txn.open_table(TRANSACTIONS_TABLE)?;
  129. let _ = write_txn.open_table(KEYSET_U32_MAPPING)?;
  130. table.insert("db_version", DATABASE_VERSION.to_string().as_str())?;
  131. }
  132. write_txn.commit()?;
  133. }
  134. }
  135. drop(db);
  136. }
  137. let db = Database::create(path)?;
  138. Ok(Self { db: Arc::new(db) })
  139. }
  140. }
  141. #[async_trait]
  142. impl WalletDatabase for WalletRedbDatabase {
  143. type Err = database::Error;
  144. #[instrument(skip(self))]
  145. async fn add_mint(
  146. &self,
  147. mint_url: MintUrl,
  148. mint_info: Option<MintInfo>,
  149. ) -> Result<(), Self::Err> {
  150. let write_txn = self.db.begin_write().map_err(Error::from)?;
  151. {
  152. let mut table = write_txn.open_table(MINTS_TABLE).map_err(Error::from)?;
  153. table
  154. .insert(
  155. mint_url.to_string().as_str(),
  156. serde_json::to_string(&mint_info)
  157. .map_err(Error::from)?
  158. .as_str(),
  159. )
  160. .map_err(Error::from)?;
  161. }
  162. write_txn.commit().map_err(Error::from)?;
  163. Ok(())
  164. }
  165. #[instrument(skip(self))]
  166. async fn remove_mint(&self, mint_url: MintUrl) -> Result<(), Self::Err> {
  167. let write_txn = self.db.begin_write().map_err(Error::from)?;
  168. {
  169. let mut table = write_txn.open_table(MINTS_TABLE).map_err(Error::from)?;
  170. table
  171. .remove(mint_url.to_string().as_str())
  172. .map_err(Error::from)?;
  173. }
  174. write_txn.commit().map_err(Error::from)?;
  175. Ok(())
  176. }
  177. #[instrument(skip(self))]
  178. async fn get_mint(&self, mint_url: MintUrl) -> Result<Option<MintInfo>, Self::Err> {
  179. let read_txn = self.db.begin_read().map_err(Into::<Error>::into)?;
  180. let table = read_txn.open_table(MINTS_TABLE).map_err(Error::from)?;
  181. if let Some(mint_info) = table
  182. .get(mint_url.to_string().as_str())
  183. .map_err(Error::from)?
  184. {
  185. return Ok(serde_json::from_str(mint_info.value()).map_err(Error::from)?);
  186. }
  187. Ok(None)
  188. }
  189. #[instrument(skip(self))]
  190. async fn get_mints(&self) -> Result<HashMap<MintUrl, Option<MintInfo>>, Self::Err> {
  191. let read_txn = self.db.begin_read().map_err(Error::from)?;
  192. let table = read_txn.open_table(MINTS_TABLE).map_err(Error::from)?;
  193. let mints = table
  194. .iter()
  195. .map_err(Error::from)?
  196. .flatten()
  197. .map(|(mint, mint_info)| {
  198. (
  199. MintUrl::from_str(mint.value()).unwrap(),
  200. serde_json::from_str(mint_info.value()).ok(),
  201. )
  202. })
  203. .collect();
  204. Ok(mints)
  205. }
  206. #[instrument(skip(self))]
  207. async fn update_mint_url(
  208. &self,
  209. old_mint_url: MintUrl,
  210. new_mint_url: MintUrl,
  211. ) -> Result<(), Self::Err> {
  212. // Update proofs table
  213. {
  214. let proofs = self
  215. .get_proofs(Some(old_mint_url.clone()), None, None, None)
  216. .await
  217. .map_err(Error::from)?;
  218. // Proofs with new url
  219. let updated_proofs: Vec<ProofInfo> = proofs
  220. .clone()
  221. .into_iter()
  222. .map(|mut p| {
  223. p.mint_url = new_mint_url.clone();
  224. p
  225. })
  226. .collect();
  227. if !updated_proofs.is_empty() {
  228. self.update_proofs(updated_proofs, vec![]).await?;
  229. }
  230. }
  231. // Update mint quotes
  232. {
  233. let quotes = self.get_mint_quotes().await?;
  234. let unix_time = unix_time();
  235. let quotes: Vec<MintQuote> = quotes
  236. .into_iter()
  237. .filter_map(|mut q| {
  238. if q.expiry < unix_time {
  239. q.mint_url = new_mint_url.clone();
  240. Some(q)
  241. } else {
  242. None
  243. }
  244. })
  245. .collect();
  246. for quote in quotes {
  247. self.add_mint_quote(quote).await?;
  248. }
  249. }
  250. Ok(())
  251. }
  252. #[instrument(skip(self))]
  253. async fn add_mint_keysets(
  254. &self,
  255. mint_url: MintUrl,
  256. keysets: Vec<KeySetInfo>,
  257. ) -> Result<(), Self::Err> {
  258. let write_txn = self.db.begin_write().map_err(Error::from)?;
  259. let mut existing_u32 = false;
  260. {
  261. let mut table = write_txn
  262. .open_multimap_table(MINT_KEYSETS_TABLE)
  263. .map_err(Error::from)?;
  264. let mut keysets_table = write_txn.open_table(KEYSETS_TABLE).map_err(Error::from)?;
  265. let mut u32_table = write_txn
  266. .open_table(KEYSET_U32_MAPPING)
  267. .map_err(Error::from)?;
  268. for keyset in keysets {
  269. // Check if keyset already exists
  270. let existing_keyset = {
  271. let existing_keyset = keysets_table
  272. .get(keyset.id.to_bytes().as_slice())
  273. .map_err(Error::from)?;
  274. existing_keyset.map(|r| r.value().to_string())
  275. };
  276. let existing = u32_table
  277. .insert(u32::from(keyset.id), keyset.id.to_string().as_str())
  278. .map_err(Error::from)?;
  279. match existing {
  280. None => existing_u32 = false,
  281. Some(id) => {
  282. let id = Id::from_str(id.value())?;
  283. if id == keyset.id {
  284. existing_u32 = false;
  285. } else {
  286. println!("Breaking here");
  287. existing_u32 = true;
  288. break;
  289. }
  290. }
  291. }
  292. let keyset = if let Some(existing_keyset) = existing_keyset {
  293. let mut existing_keyset: KeySetInfo = serde_json::from_str(&existing_keyset)?;
  294. existing_keyset.active = keyset.active;
  295. existing_keyset.input_fee_ppk = keyset.input_fee_ppk;
  296. existing_keyset
  297. } else {
  298. table
  299. .insert(
  300. mint_url.to_string().as_str(),
  301. keyset.id.to_bytes().as_slice(),
  302. )
  303. .map_err(Error::from)?;
  304. keyset
  305. };
  306. keysets_table
  307. .insert(
  308. keyset.id.to_bytes().as_slice(),
  309. serde_json::to_string(&keyset)
  310. .map_err(Error::from)?
  311. .as_str(),
  312. )
  313. .map_err(Error::from)?;
  314. }
  315. }
  316. if existing_u32 {
  317. tracing::warn!("Keyset already exists for keyset id");
  318. write_txn.abort().map_err(Error::from)?;
  319. return Err(database::Error::Duplicate);
  320. }
  321. write_txn.commit().map_err(Error::from)?;
  322. Ok(())
  323. }
  324. #[instrument(skip(self))]
  325. async fn get_mint_keysets(
  326. &self,
  327. mint_url: MintUrl,
  328. ) -> Result<Option<Vec<KeySetInfo>>, Self::Err> {
  329. let read_txn = self.db.begin_read().map_err(Into::<Error>::into)?;
  330. let table = read_txn
  331. .open_multimap_table(MINT_KEYSETS_TABLE)
  332. .map_err(Error::from)?;
  333. let keyset_ids = table
  334. .get(mint_url.to_string().as_str())
  335. .map_err(Error::from)?
  336. .flatten()
  337. .map(|k| Id::from_bytes(k.value()))
  338. .collect::<Result<Vec<_>, _>>()?;
  339. let mut keysets = vec![];
  340. let keysets_t = read_txn.open_table(KEYSETS_TABLE).map_err(Error::from)?;
  341. for keyset_id in keyset_ids {
  342. if let Some(keyset) = keysets_t
  343. .get(keyset_id.to_bytes().as_slice())
  344. .map_err(Error::from)?
  345. {
  346. let keyset = serde_json::from_str(keyset.value()).map_err(Error::from)?;
  347. keysets.push(keyset);
  348. }
  349. }
  350. match keysets.is_empty() {
  351. true => Ok(None),
  352. false => Ok(Some(keysets)),
  353. }
  354. }
  355. #[instrument(skip(self), fields(keyset_id = %keyset_id))]
  356. async fn get_keyset_by_id(&self, keyset_id: &Id) -> Result<Option<KeySetInfo>, Self::Err> {
  357. let read_txn = self.db.begin_read().map_err(Into::<Error>::into)?;
  358. let table = read_txn.open_table(KEYSETS_TABLE).map_err(Error::from)?;
  359. match table
  360. .get(keyset_id.to_bytes().as_slice())
  361. .map_err(Error::from)?
  362. {
  363. Some(keyset) => {
  364. let keyset: KeySetInfo =
  365. serde_json::from_str(keyset.value()).map_err(Error::from)?;
  366. Ok(Some(keyset))
  367. }
  368. None => Ok(None),
  369. }
  370. }
  371. #[instrument(skip_all)]
  372. async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), Self::Err> {
  373. let write_txn = self.db.begin_write().map_err(Error::from)?;
  374. {
  375. let mut table = write_txn
  376. .open_table(MINT_QUOTES_TABLE)
  377. .map_err(Error::from)?;
  378. table
  379. .insert(
  380. quote.id.as_str(),
  381. serde_json::to_string(&quote).map_err(Error::from)?.as_str(),
  382. )
  383. .map_err(Error::from)?;
  384. }
  385. write_txn.commit().map_err(Error::from)?;
  386. Ok(())
  387. }
  388. #[instrument(skip_all)]
  389. async fn get_mint_quote(&self, quote_id: &str) -> Result<Option<MintQuote>, Self::Err> {
  390. let read_txn = self.db.begin_read().map_err(Into::<Error>::into)?;
  391. let table = read_txn
  392. .open_table(MINT_QUOTES_TABLE)
  393. .map_err(Error::from)?;
  394. if let Some(mint_info) = table.get(quote_id).map_err(Error::from)? {
  395. return Ok(serde_json::from_str(mint_info.value()).map_err(Error::from)?);
  396. }
  397. Ok(None)
  398. }
  399. #[instrument(skip_all)]
  400. async fn get_mint_quotes(&self) -> Result<Vec<MintQuote>, Self::Err> {
  401. let read_txn = self.db.begin_read().map_err(Into::<Error>::into)?;
  402. let table = read_txn
  403. .open_table(MINT_QUOTES_TABLE)
  404. .map_err(Error::from)?;
  405. Ok(table
  406. .iter()
  407. .map_err(Error::from)?
  408. .flatten()
  409. .flat_map(|(_id, quote)| serde_json::from_str(quote.value()))
  410. .collect())
  411. }
  412. #[instrument(skip_all)]
  413. async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), Self::Err> {
  414. let write_txn = self.db.begin_write().map_err(Error::from)?;
  415. {
  416. let mut table = write_txn
  417. .open_table(MINT_QUOTES_TABLE)
  418. .map_err(Error::from)?;
  419. table.remove(quote_id).map_err(Error::from)?;
  420. }
  421. write_txn.commit().map_err(Error::from)?;
  422. Ok(())
  423. }
  424. #[instrument(skip_all)]
  425. async fn add_melt_quote(&self, quote: wallet::MeltQuote) -> Result<(), Self::Err> {
  426. let write_txn = self.db.begin_write().map_err(Error::from)?;
  427. {
  428. let mut table = write_txn
  429. .open_table(MELT_QUOTES_TABLE)
  430. .map_err(Error::from)?;
  431. table
  432. .insert(
  433. quote.id.as_str(),
  434. serde_json::to_string(&quote).map_err(Error::from)?.as_str(),
  435. )
  436. .map_err(Error::from)?;
  437. }
  438. write_txn.commit().map_err(Error::from)?;
  439. Ok(())
  440. }
  441. #[instrument(skip_all)]
  442. async fn get_melt_quote(&self, quote_id: &str) -> Result<Option<wallet::MeltQuote>, Self::Err> {
  443. let read_txn = self.db.begin_read().map_err(Error::from)?;
  444. let table = read_txn
  445. .open_table(MELT_QUOTES_TABLE)
  446. .map_err(Error::from)?;
  447. if let Some(mint_info) = table.get(quote_id).map_err(Error::from)? {
  448. return Ok(serde_json::from_str(mint_info.value()).map_err(Error::from)?);
  449. }
  450. Ok(None)
  451. }
  452. #[instrument(skip_all)]
  453. async fn get_melt_quotes(&self) -> Result<Vec<wallet::MeltQuote>, Self::Err> {
  454. let read_txn = self.db.begin_read().map_err(Error::from)?;
  455. let table = read_txn
  456. .open_table(MELT_QUOTES_TABLE)
  457. .map_err(Error::from)?;
  458. Ok(table
  459. .iter()
  460. .map_err(Error::from)?
  461. .flatten()
  462. .flat_map(|(_id, quote)| serde_json::from_str(quote.value()))
  463. .collect())
  464. }
  465. #[instrument(skip_all)]
  466. async fn remove_melt_quote(&self, quote_id: &str) -> Result<(), Self::Err> {
  467. let write_txn = self.db.begin_write().map_err(Error::from)?;
  468. {
  469. let mut table = write_txn
  470. .open_table(MELT_QUOTES_TABLE)
  471. .map_err(Error::from)?;
  472. table.remove(quote_id).map_err(Error::from)?;
  473. }
  474. write_txn.commit().map_err(Error::from)?;
  475. Ok(())
  476. }
  477. #[instrument(skip_all)]
  478. async fn add_keys(&self, keyset: KeySet) -> Result<(), Self::Err> {
  479. let write_txn = self.db.begin_write().map_err(Error::from)?;
  480. keyset.verify_id()?;
  481. let existing_keys;
  482. let existing_u32;
  483. {
  484. let mut table = write_txn.open_table(MINT_KEYS_TABLE).map_err(Error::from)?;
  485. existing_keys = table
  486. .insert(
  487. keyset.id.to_string().as_str(),
  488. serde_json::to_string(&keyset.keys)
  489. .map_err(Error::from)?
  490. .as_str(),
  491. )
  492. .map_err(Error::from)?
  493. .is_some();
  494. let mut table = write_txn
  495. .open_table(KEYSET_U32_MAPPING)
  496. .map_err(Error::from)?;
  497. let existing = table
  498. .insert(u32::from(keyset.id), keyset.id.to_string().as_str())
  499. .map_err(Error::from)?;
  500. match existing {
  501. None => existing_u32 = false,
  502. Some(id) => {
  503. let id = Id::from_str(id.value())?;
  504. existing_u32 = id != keyset.id;
  505. }
  506. }
  507. }
  508. if existing_keys || existing_u32 {
  509. tracing::warn!("Keys already exist for keyset id");
  510. write_txn.abort().map_err(Error::from)?;
  511. return Err(database::Error::Duplicate);
  512. }
  513. write_txn.commit().map_err(Error::from)?;
  514. Ok(())
  515. }
  516. #[instrument(skip(self), fields(keyset_id = %keyset_id))]
  517. async fn get_keys(&self, keyset_id: &Id) -> Result<Option<Keys>, Self::Err> {
  518. let read_txn = self.db.begin_read().map_err(Error::from)?;
  519. let table = read_txn.open_table(MINT_KEYS_TABLE).map_err(Error::from)?;
  520. if let Some(mint_info) = table
  521. .get(keyset_id.to_string().as_str())
  522. .map_err(Error::from)?
  523. {
  524. return Ok(serde_json::from_str(mint_info.value()).map_err(Error::from)?);
  525. }
  526. Ok(None)
  527. }
  528. #[instrument(skip(self), fields(keyset_id = %keyset_id))]
  529. async fn remove_keys(&self, keyset_id: &Id) -> Result<(), Self::Err> {
  530. let write_txn = self.db.begin_write().map_err(Error::from)?;
  531. {
  532. let mut table = write_txn.open_table(MINT_KEYS_TABLE).map_err(Error::from)?;
  533. table
  534. .remove(keyset_id.to_string().as_str())
  535. .map_err(Error::from)?;
  536. }
  537. write_txn.commit().map_err(Error::from)?;
  538. Ok(())
  539. }
  540. #[instrument(skip(self, added, deleted_ys))]
  541. async fn update_proofs(
  542. &self,
  543. added: Vec<ProofInfo>,
  544. deleted_ys: Vec<PublicKey>,
  545. ) -> Result<(), Self::Err> {
  546. let write_txn = self.db.begin_write().map_err(Error::from)?;
  547. {
  548. let mut table = write_txn.open_table(PROOFS_TABLE).map_err(Error::from)?;
  549. for proof_info in added.iter() {
  550. table
  551. .insert(
  552. proof_info.y.to_bytes().as_slice(),
  553. serde_json::to_string(&proof_info)
  554. .map_err(Error::from)?
  555. .as_str(),
  556. )
  557. .map_err(Error::from)?;
  558. }
  559. for y in deleted_ys.iter() {
  560. table.remove(y.to_bytes().as_slice()).map_err(Error::from)?;
  561. }
  562. }
  563. write_txn.commit().map_err(Error::from)?;
  564. Ok(())
  565. }
  566. #[instrument(skip_all)]
  567. async fn get_proofs(
  568. &self,
  569. mint_url: Option<MintUrl>,
  570. unit: Option<CurrencyUnit>,
  571. state: Option<Vec<State>>,
  572. spending_conditions: Option<Vec<SpendingConditions>>,
  573. ) -> Result<Vec<ProofInfo>, Self::Err> {
  574. let read_txn = self.db.begin_read().map_err(Error::from)?;
  575. let table = read_txn.open_table(PROOFS_TABLE).map_err(Error::from)?;
  576. let proofs: Vec<ProofInfo> = table
  577. .iter()
  578. .map_err(Error::from)?
  579. .flatten()
  580. .filter_map(|(_k, v)| {
  581. let mut proof = None;
  582. if let Ok(proof_info) = serde_json::from_str::<ProofInfo>(v.value()) {
  583. if proof_info.matches_conditions(&mint_url, &unit, &state, &spending_conditions)
  584. {
  585. proof = Some(proof_info)
  586. }
  587. }
  588. proof
  589. })
  590. .collect();
  591. Ok(proofs)
  592. }
  593. async fn update_proofs_state(
  594. &self,
  595. ys: Vec<PublicKey>,
  596. state: State,
  597. ) -> Result<(), database::Error> {
  598. let read_txn = self.db.begin_read().map_err(Error::from)?;
  599. let table = read_txn.open_table(PROOFS_TABLE).map_err(Error::from)?;
  600. let write_txn = self.db.begin_write().map_err(Error::from)?;
  601. for y in ys {
  602. let y_slice = y.to_bytes();
  603. let proof = table
  604. .get(y_slice.as_slice())
  605. .map_err(Error::from)?
  606. .ok_or(Error::UnknownY)?;
  607. let mut proof_info =
  608. serde_json::from_str::<ProofInfo>(proof.value()).map_err(Error::from)?;
  609. proof_info.state = state;
  610. {
  611. let mut table = write_txn.open_table(PROOFS_TABLE).map_err(Error::from)?;
  612. table
  613. .insert(
  614. y_slice.as_slice(),
  615. serde_json::to_string(&proof_info)
  616. .map_err(Error::from)?
  617. .as_str(),
  618. )
  619. .map_err(Error::from)?;
  620. }
  621. }
  622. write_txn.commit().map_err(Error::from)?;
  623. Ok(())
  624. }
  625. #[instrument(skip(self), fields(keyset_id = %keyset_id))]
  626. async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<u32, Self::Err> {
  627. let write_txn = self.db.begin_write().map_err(Error::from)?;
  628. let current_counter;
  629. let new_counter;
  630. {
  631. let table = write_txn.open_table(KEYSET_COUNTER).map_err(Error::from)?;
  632. let counter = table
  633. .get(keyset_id.to_string().as_str())
  634. .map_err(Error::from)?;
  635. current_counter = match counter {
  636. Some(c) => c.value(),
  637. None => 0,
  638. };
  639. new_counter = current_counter + count;
  640. }
  641. {
  642. let mut table = write_txn.open_table(KEYSET_COUNTER).map_err(Error::from)?;
  643. table
  644. .insert(keyset_id.to_string().as_str(), new_counter)
  645. .map_err(Error::from)?;
  646. }
  647. write_txn.commit().map_err(Error::from)?;
  648. Ok(new_counter)
  649. }
  650. #[instrument(skip(self))]
  651. async fn add_transaction(&self, transaction: Transaction) -> Result<(), Self::Err> {
  652. let write_txn = self.db.begin_write().map_err(Error::from)?;
  653. {
  654. let mut table = write_txn
  655. .open_table(TRANSACTIONS_TABLE)
  656. .map_err(Error::from)?;
  657. table
  658. .insert(
  659. transaction.id().as_slice(),
  660. serde_json::to_string(&transaction)
  661. .map_err(Error::from)?
  662. .as_str(),
  663. )
  664. .map_err(Error::from)?;
  665. }
  666. write_txn.commit().map_err(Error::from)?;
  667. Ok(())
  668. }
  669. #[instrument(skip(self))]
  670. async fn get_transaction(
  671. &self,
  672. transaction_id: TransactionId,
  673. ) -> Result<Option<Transaction>, Self::Err> {
  674. let read_txn = self.db.begin_read().map_err(Error::from)?;
  675. let table = read_txn
  676. .open_table(TRANSACTIONS_TABLE)
  677. .map_err(Error::from)?;
  678. if let Some(transaction) = table.get(transaction_id.as_slice()).map_err(Error::from)? {
  679. return Ok(serde_json::from_str(transaction.value()).map_err(Error::from)?);
  680. }
  681. Ok(None)
  682. }
  683. #[instrument(skip(self))]
  684. async fn list_transactions(
  685. &self,
  686. mint_url: Option<MintUrl>,
  687. direction: Option<TransactionDirection>,
  688. unit: Option<CurrencyUnit>,
  689. ) -> Result<Vec<Transaction>, Self::Err> {
  690. let read_txn = self.db.begin_read().map_err(Error::from)?;
  691. let table = read_txn
  692. .open_table(TRANSACTIONS_TABLE)
  693. .map_err(Error::from)?;
  694. let transactions: Vec<Transaction> = table
  695. .iter()
  696. .map_err(Error::from)?
  697. .flatten()
  698. .filter_map(|(_k, v)| {
  699. let mut transaction = None;
  700. if let Ok(tx) = serde_json::from_str::<Transaction>(v.value()) {
  701. if tx.matches_conditions(&mint_url, &direction, &unit) {
  702. transaction = Some(tx)
  703. }
  704. }
  705. transaction
  706. })
  707. .collect();
  708. Ok(transactions)
  709. }
  710. #[instrument(skip(self))]
  711. async fn remove_transaction(&self, transaction_id: TransactionId) -> Result<(), Self::Err> {
  712. let write_txn = self.db.begin_write().map_err(Error::from)?;
  713. {
  714. let mut table = write_txn
  715. .open_table(TRANSACTIONS_TABLE)
  716. .map_err(Error::from)?;
  717. table
  718. .remove(transaction_id.as_slice())
  719. .map_err(Error::from)?;
  720. }
  721. write_txn.commit().map_err(Error::from)?;
  722. Ok(())
  723. }
  724. }