mint.rs 17 KB

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