mint.rs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. use std::collections::HashMap;
  2. use std::str::FromStr;
  3. use std::sync::Arc;
  4. use async_trait::async_trait;
  5. use cdk::cdk_database;
  6. use cdk::cdk_database::MintDatabase;
  7. use cdk::dhke::hash_to_curve;
  8. use cdk::mint::MintKeySetInfo;
  9. use cdk::nuts::{BlindSignature, CurrencyUnit, Id, MintInfo, Proof, PublicKey};
  10. use cdk::secret::Secret;
  11. use cdk::types::{MeltQuote, MintQuote};
  12. use redb::{Database, ReadableTable, TableDefinition};
  13. use tokio::sync::Mutex;
  14. use tracing::debug;
  15. use super::error::Error;
  16. const ACTIVE_KEYSETS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("active_keysets");
  17. const KEYSETS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("keysets");
  18. const MINT_QUOTES_TABLE: TableDefinition<&str, &str> = TableDefinition::new("mint_quotes");
  19. const MELT_QUOTES_TABLE: TableDefinition<&str, &str> = TableDefinition::new("melt_quotes");
  20. const PENDING_PROOFS_TABLE: TableDefinition<[u8; 33], &str> =
  21. TableDefinition::new("pending_proofs");
  22. const SPENT_PROOFS_TABLE: TableDefinition<[u8; 33], &str> = TableDefinition::new("spent_proofs");
  23. const CONFIG_TABLE: TableDefinition<&str, &str> = TableDefinition::new("config");
  24. // Key is hex blinded_message B_ value is blinded_signature
  25. const BLINDED_SIGNATURES: TableDefinition<[u8; 33], &str> =
  26. TableDefinition::new("blinded_signatures");
  27. const DATABASE_VERSION: u64 = 0;
  28. #[derive(Debug, Clone)]
  29. pub struct MintRedbDatabase {
  30. db: Arc<Mutex<Database>>,
  31. }
  32. impl MintRedbDatabase {
  33. pub fn new(path: &str) -> Result<Self, Error> {
  34. let db = Database::create(path)?;
  35. let write_txn = db.begin_write()?;
  36. // Check database version
  37. {
  38. let _ = write_txn.open_table(CONFIG_TABLE)?;
  39. let mut table = write_txn.open_table(CONFIG_TABLE)?;
  40. let db_version = table.get("db_version")?;
  41. let db_version = db_version.map(|v| v.value().to_owned());
  42. match db_version {
  43. Some(db_version) => {
  44. let current_file_version = u64::from_str(&db_version)?;
  45. if current_file_version.ne(&DATABASE_VERSION) {
  46. // Database needs to be upgraded
  47. todo!()
  48. }
  49. }
  50. None => {
  51. // Open all tables to init a new db
  52. let _ = write_txn.open_table(ACTIVE_KEYSETS_TABLE)?;
  53. let _ = write_txn.open_table(KEYSETS_TABLE)?;
  54. let _ = write_txn.open_table(MINT_QUOTES_TABLE)?;
  55. let _ = write_txn.open_table(MELT_QUOTES_TABLE)?;
  56. let _ = write_txn.open_table(PENDING_PROOFS_TABLE)?;
  57. let _ = write_txn.open_table(SPENT_PROOFS_TABLE)?;
  58. let _ = write_txn.open_table(BLINDED_SIGNATURES)?;
  59. table.insert("db_version", "0")?;
  60. }
  61. }
  62. }
  63. write_txn.commit()?;
  64. Ok(Self {
  65. db: Arc::new(Mutex::new(db)),
  66. })
  67. }
  68. }
  69. #[async_trait]
  70. impl MintDatabase for MintRedbDatabase {
  71. type Err = cdk_database::Error;
  72. async fn set_mint_info(&self, mint_info: &MintInfo) -> Result<(), Self::Err> {
  73. let db = self.db.lock().await;
  74. let write_txn = db.begin_write().map_err(Error::from)?;
  75. {
  76. let mut table = write_txn.open_table(CONFIG_TABLE).map_err(Error::from)?;
  77. table
  78. .insert(
  79. "mint_info",
  80. serde_json::to_string(mint_info)
  81. .map_err(Error::from)?
  82. .as_str(),
  83. )
  84. .map_err(Error::from)?;
  85. }
  86. write_txn.commit().map_err(Error::from)?;
  87. Ok(())
  88. }
  89. async fn get_mint_info(&self) -> Result<MintInfo, Self::Err> {
  90. let db = self.db.lock().await;
  91. let read_txn = db.begin_read().map_err(Error::from)?;
  92. let table = read_txn.open_table(CONFIG_TABLE).map_err(Error::from)?;
  93. let mint_info = table
  94. .get("mint_info")
  95. .map_err(Error::from)?
  96. .ok_or(Error::UnknownMintInfo)?;
  97. Ok(serde_json::from_str(mint_info.value()).map_err(Error::from)?)
  98. }
  99. async fn add_active_keyset(&self, unit: CurrencyUnit, id: Id) -> Result<(), Self::Err> {
  100. let db = self.db.lock().await;
  101. let write_txn = db.begin_write().map_err(Error::from)?;
  102. {
  103. let mut table = write_txn
  104. .open_table(ACTIVE_KEYSETS_TABLE)
  105. .map_err(Error::from)?;
  106. table
  107. .insert(unit.to_string().as_str(), id.to_string().as_str())
  108. .map_err(Error::from)?;
  109. }
  110. write_txn.commit().map_err(Error::from)?;
  111. Ok(())
  112. }
  113. async fn get_active_keyset_id(&self, unit: &CurrencyUnit) -> Result<Option<Id>, Self::Err> {
  114. let db = self.db.lock().await;
  115. let read_txn = db.begin_read().map_err(Error::from)?;
  116. let table = read_txn
  117. .open_table(ACTIVE_KEYSETS_TABLE)
  118. .map_err(Error::from)?;
  119. if let Some(id) = table.get(unit.to_string().as_str()).map_err(Error::from)? {
  120. return Ok(Some(Id::from_str(id.value()).map_err(Error::from)?));
  121. }
  122. Ok(None)
  123. }
  124. async fn get_active_keysets(&self) -> Result<HashMap<CurrencyUnit, Id>, Self::Err> {
  125. let db = self.db.lock().await;
  126. let read_txn = db.begin_read().map_err(Error::from)?;
  127. let table = read_txn
  128. .open_table(ACTIVE_KEYSETS_TABLE)
  129. .map_err(Error::from)?;
  130. let mut active_keysets = HashMap::new();
  131. for (unit, id) in (table.iter().map_err(Error::from)?).flatten() {
  132. let unit = CurrencyUnit::from(unit.value());
  133. let id = Id::from_str(id.value()).map_err(Error::from)?;
  134. active_keysets.insert(unit, id);
  135. }
  136. Ok(active_keysets)
  137. }
  138. async fn add_keyset_info(&self, keyset: MintKeySetInfo) -> Result<(), Self::Err> {
  139. let db = self.db.lock().await;
  140. let write_txn = db.begin_write().map_err(Error::from)?;
  141. {
  142. let mut table = write_txn.open_table(KEYSETS_TABLE).map_err(Error::from)?;
  143. table
  144. .insert(
  145. keyset.id.to_string().as_str(),
  146. serde_json::to_string(&keyset)
  147. .map_err(Error::from)?
  148. .as_str(),
  149. )
  150. .map_err(Error::from)?;
  151. }
  152. write_txn.commit().map_err(Error::from)?;
  153. Ok(())
  154. }
  155. async fn get_keyset_info(&self, keyset_id: &Id) -> Result<Option<MintKeySetInfo>, Self::Err> {
  156. let db = self.db.lock().await;
  157. let read_txn = db.begin_read().map_err(Error::from)?;
  158. let table = read_txn.open_table(KEYSETS_TABLE).map_err(Error::from)?;
  159. match table
  160. .get(keyset_id.to_string().as_str())
  161. .map_err(Error::from)?
  162. {
  163. Some(keyset) => Ok(serde_json::from_str(keyset.value()).map_err(Error::from)?),
  164. None => Ok(None),
  165. }
  166. }
  167. async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err> {
  168. let db = self.db.lock().await;
  169. let read_txn = db.begin_read().map_err(Error::from)?;
  170. let table = read_txn.open_table(KEYSETS_TABLE).map_err(Error::from)?;
  171. let mut keysets = Vec::new();
  172. for (_id, keyset) in (table.iter().map_err(Error::from)?).flatten() {
  173. let keyset = serde_json::from_str(keyset.value()).map_err(Error::from)?;
  174. keysets.push(keyset)
  175. }
  176. Ok(keysets)
  177. }
  178. async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), Self::Err> {
  179. let db = self.db.lock().await;
  180. let write_txn = db.begin_write().map_err(Error::from)?;
  181. {
  182. let mut table = write_txn
  183. .open_table(MINT_QUOTES_TABLE)
  184. .map_err(Error::from)?;
  185. table
  186. .insert(
  187. quote.id.as_str(),
  188. serde_json::to_string(&quote).map_err(Error::from)?.as_str(),
  189. )
  190. .map_err(Error::from)?;
  191. }
  192. write_txn.commit().map_err(Error::from)?;
  193. Ok(())
  194. }
  195. async fn get_mint_quote(&self, quote_id: &str) -> Result<Option<MintQuote>, Self::Err> {
  196. let db = self.db.lock().await;
  197. let read_txn = db.begin_read().map_err(Error::from)?;
  198. let table = read_txn
  199. .open_table(MINT_QUOTES_TABLE)
  200. .map_err(Error::from)?;
  201. match table.get(quote_id).map_err(Error::from)? {
  202. Some(quote) => Ok(serde_json::from_str(quote.value()).map_err(Error::from)?),
  203. None => Ok(None),
  204. }
  205. }
  206. async fn get_mint_quotes(&self) -> Result<Vec<MintQuote>, Self::Err> {
  207. let db = self.db.lock().await;
  208. let read_txn = db.begin_read().map_err(Error::from)?;
  209. let table = read_txn
  210. .open_table(MINT_QUOTES_TABLE)
  211. .map_err(Error::from)?;
  212. let mut quotes = Vec::new();
  213. for (_id, quote) in (table.iter().map_err(Error::from)?).flatten() {
  214. let quote = serde_json::from_str(quote.value()).map_err(Error::from)?;
  215. quotes.push(quote)
  216. }
  217. Ok(quotes)
  218. }
  219. async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), Self::Err> {
  220. let db = self.db.lock().await;
  221. let write_txn = db.begin_write().map_err(Error::from)?;
  222. {
  223. let mut table = write_txn
  224. .open_table(MINT_QUOTES_TABLE)
  225. .map_err(Error::from)?;
  226. table.remove(quote_id).map_err(Error::from)?;
  227. }
  228. write_txn.commit().map_err(Error::from)?;
  229. Ok(())
  230. }
  231. async fn add_melt_quote(&self, quote: MeltQuote) -> Result<(), Self::Err> {
  232. let db = self.db.lock().await;
  233. let write_txn = db.begin_write().map_err(Error::from)?;
  234. {
  235. let mut table = write_txn
  236. .open_table(MELT_QUOTES_TABLE)
  237. .map_err(Error::from)?;
  238. table
  239. .insert(
  240. quote.id.as_str(),
  241. serde_json::to_string(&quote).map_err(Error::from)?.as_str(),
  242. )
  243. .map_err(Error::from)?;
  244. }
  245. write_txn.commit().map_err(Error::from)?;
  246. Ok(())
  247. }
  248. async fn get_melt_quote(&self, quote_id: &str) -> Result<Option<MeltQuote>, Self::Err> {
  249. let db = self.db.lock().await;
  250. let read_txn = db.begin_read().map_err(Error::from)?;
  251. let table = read_txn
  252. .open_table(MELT_QUOTES_TABLE)
  253. .map_err(Error::from)?;
  254. let quote = table.get(quote_id).map_err(Error::from)?;
  255. Ok(quote.map(|q| serde_json::from_str(q.value()).unwrap()))
  256. }
  257. async fn get_melt_quotes(&self) -> Result<Vec<MeltQuote>, Self::Err> {
  258. let db = self.db.lock().await;
  259. let read_txn = db.begin_read().map_err(Error::from)?;
  260. let table = read_txn
  261. .open_table(MELT_QUOTES_TABLE)
  262. .map_err(Error::from)?;
  263. let mut quotes = Vec::new();
  264. for (_id, quote) in (table.iter().map_err(Error::from)?).flatten() {
  265. let quote = serde_json::from_str(quote.value()).map_err(Error::from)?;
  266. quotes.push(quote)
  267. }
  268. Ok(quotes)
  269. }
  270. async fn remove_melt_quote(&self, quote_id: &str) -> Result<(), Self::Err> {
  271. let db = self.db.lock().await;
  272. let write_txn = db.begin_write().map_err(Error::from)?;
  273. {
  274. let mut table = write_txn
  275. .open_table(MELT_QUOTES_TABLE)
  276. .map_err(Error::from)?;
  277. table.remove(quote_id).map_err(Error::from)?;
  278. }
  279. write_txn.commit().map_err(Error::from)?;
  280. Ok(())
  281. }
  282. async fn add_spent_proof(&self, proof: Proof) -> Result<(), Self::Err> {
  283. let db = self.db.lock().await;
  284. let write_txn = db.begin_write().map_err(Error::from)?;
  285. {
  286. let mut table = write_txn
  287. .open_table(SPENT_PROOFS_TABLE)
  288. .map_err(Error::from)?;
  289. let y: PublicKey = hash_to_curve(&proof.secret.to_bytes()).map_err(Error::from)?;
  290. table
  291. .insert(
  292. y.to_bytes(),
  293. serde_json::to_string(&proof).map_err(Error::from)?.as_str(),
  294. )
  295. .map_err(Error::from)?;
  296. }
  297. write_txn.commit().map_err(Error::from)?;
  298. debug!("Added spend secret: {}", proof.secret.to_string());
  299. Ok(())
  300. }
  301. async fn get_spent_proof_by_y(&self, y: &PublicKey) -> Result<Option<Proof>, Self::Err> {
  302. let db = self.db.lock().await;
  303. let read_txn = db.begin_read().map_err(Error::from)?;
  304. let table = read_txn
  305. .open_table(SPENT_PROOFS_TABLE)
  306. .map_err(Error::from)?;
  307. match table.get(y.to_bytes()).map_err(Error::from)? {
  308. Some(proof) => Ok(serde_json::from_str(proof.value()).map_err(Error::from)?),
  309. None => Ok(None),
  310. }
  311. }
  312. async fn get_spent_proof_by_secret(&self, secret: &Secret) -> Result<Option<Proof>, Self::Err> {
  313. let db = self.db.lock().await;
  314. let read_txn = db.begin_read().map_err(Error::from)?;
  315. let table = read_txn
  316. .open_table(SPENT_PROOFS_TABLE)
  317. .map_err(Error::from)?;
  318. let y: PublicKey = hash_to_curve(&secret.to_bytes())?;
  319. match table.get(y.to_bytes()).map_err(Error::from)? {
  320. Some(proof) => Ok(serde_json::from_str(proof.value()).map_err(Error::from)?),
  321. None => Ok(None),
  322. }
  323. }
  324. async fn add_pending_proof(&self, proof: Proof) -> Result<(), Self::Err> {
  325. let db = self.db.lock().await;
  326. let write_txn = db.begin_write().map_err(Error::from)?;
  327. {
  328. let mut table = write_txn
  329. .open_table(PENDING_PROOFS_TABLE)
  330. .map_err(Error::from)?;
  331. table
  332. .insert(
  333. hash_to_curve(&proof.secret.to_bytes())?.to_bytes(),
  334. serde_json::to_string(&proof).map_err(Error::from)?.as_str(),
  335. )
  336. .map_err(Error::from)?;
  337. }
  338. write_txn.commit().map_err(Error::from)?;
  339. Ok(())
  340. }
  341. async fn get_pending_proof_by_y(&self, y: &PublicKey) -> Result<Option<Proof>, Self::Err> {
  342. let db = self.db.lock().await;
  343. let read_txn = db.begin_read().map_err(Error::from)?;
  344. let table = read_txn
  345. .open_table(PENDING_PROOFS_TABLE)
  346. .map_err(Error::from)?;
  347. match table.get(y.to_bytes()).map_err(Error::from)? {
  348. Some(proof) => Ok(serde_json::from_str(proof.value()).map_err(Error::from)?),
  349. None => Ok(None),
  350. }
  351. }
  352. async fn get_pending_proof_by_secret(
  353. &self,
  354. secret: &Secret,
  355. ) -> Result<Option<Proof>, Self::Err> {
  356. let db = self.db.lock().await;
  357. let read_txn = db.begin_read().map_err(Error::from)?;
  358. let table = read_txn
  359. .open_table(PENDING_PROOFS_TABLE)
  360. .map_err(Error::from)?;
  361. let secret_hash = hash_to_curve(&secret.to_bytes())?;
  362. match table.get(secret_hash.to_bytes()).map_err(Error::from)? {
  363. Some(proof) => Ok(serde_json::from_str(proof.value()).map_err(Error::from)?),
  364. None => Ok(None),
  365. }
  366. }
  367. async fn remove_pending_proof(&self, secret: &Secret) -> Result<(), Self::Err> {
  368. let db = self.db.lock().await;
  369. let write_txn = db.begin_write().map_err(Error::from)?;
  370. {
  371. let mut table = write_txn
  372. .open_table(PENDING_PROOFS_TABLE)
  373. .map_err(Error::from)?;
  374. let secret_hash = hash_to_curve(&secret.to_bytes()).map_err(Error::from)?;
  375. table.remove(secret_hash.to_bytes()).map_err(Error::from)?;
  376. }
  377. write_txn.commit().map_err(Error::from)?;
  378. Ok(())
  379. }
  380. async fn add_blinded_signature(
  381. &self,
  382. blinded_message: PublicKey,
  383. blinded_signature: BlindSignature,
  384. ) -> Result<(), Self::Err> {
  385. let db = self.db.lock().await;
  386. let write_txn = db.begin_write().map_err(Error::from)?;
  387. {
  388. let mut table = write_txn
  389. .open_table(BLINDED_SIGNATURES)
  390. .map_err(Error::from)?;
  391. table
  392. .insert(
  393. blinded_message.to_bytes(),
  394. serde_json::to_string(&blinded_signature)
  395. .map_err(Error::from)?
  396. .as_str(),
  397. )
  398. .map_err(Error::from)?;
  399. }
  400. write_txn.commit().map_err(Error::from)?;
  401. Ok(())
  402. }
  403. async fn get_blinded_signature(
  404. &self,
  405. blinded_message: &PublicKey,
  406. ) -> Result<Option<BlindSignature>, Self::Err> {
  407. let db = self.db.lock().await;
  408. let read_txn = db.begin_read().map_err(Error::from)?;
  409. let table = read_txn
  410. .open_table(BLINDED_SIGNATURES)
  411. .map_err(Error::from)?;
  412. match table.get(blinded_message.to_bytes()).map_err(Error::from)? {
  413. Some(blind_signature) => {
  414. Ok(serde_json::from_str(blind_signature.value()).map_err(Error::from)?)
  415. }
  416. None => Ok(None),
  417. }
  418. }
  419. async fn get_blinded_signatures(
  420. &self,
  421. blinded_messages: Vec<PublicKey>,
  422. ) -> Result<Vec<Option<BlindSignature>>, Self::Err> {
  423. let db = self.db.lock().await;
  424. let read_txn = db.begin_read().map_err(Error::from)?;
  425. let table = read_txn
  426. .open_table(BLINDED_SIGNATURES)
  427. .map_err(Error::from)?;
  428. let mut signatures = Vec::with_capacity(blinded_messages.len());
  429. for blinded_message in blinded_messages {
  430. match table.get(blinded_message.to_bytes()).map_err(Error::from)? {
  431. Some(blind_signature) => signatures.push(Some(
  432. serde_json::from_str(blind_signature.value()).map_err(Error::from)?,
  433. )),
  434. None => signatures.push(None),
  435. }
  436. }
  437. Ok(signatures)
  438. }
  439. }