cashierdb.rs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. use std::{fs::create_dir_all, path::Path, str::FromStr, time::Duration};
  2. use async_std::sync::Arc;
  3. use incrementalmerkletree::bridgetree::BridgeTree;
  4. use log::{debug, error, info, LevelFilter};
  5. use sqlx::{
  6. sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions},
  7. ConnectOptions, Row, SqlitePool,
  8. };
  9. use crate::{
  10. crypto::{
  11. keypair::{Keypair, PublicKey, SecretKey},
  12. merkle_node::MerkleNode,
  13. types::DrkTokenId,
  14. },
  15. util::{
  16. serial::{deserialize, serialize},
  17. NetworkName,
  18. },
  19. Error::{WalletEmptyPassword, WalletTreeExists},
  20. Result,
  21. };
  22. pub type CashierDbPtr = Arc<CashierDb>;
  23. #[derive(Debug, Clone)]
  24. pub struct TokenKey {
  25. pub public_key: Vec<u8>,
  26. pub secret_key: Vec<u8>,
  27. }
  28. pub struct WithdrawToken {
  29. pub token_public_key: Vec<u8>,
  30. pub network: NetworkName,
  31. pub token_id: DrkTokenId,
  32. pub mint_address: String,
  33. }
  34. pub struct DepositToken {
  35. pub drk_public_key: PublicKey,
  36. pub token_key: TokenKey,
  37. pub token_id: DrkTokenId,
  38. pub mint_address: String,
  39. }
  40. pub struct CashierDb {
  41. pub conn: SqlitePool,
  42. }
  43. impl CashierDb {
  44. pub async fn new(path: &str, password: &str) -> Result<CashierDbPtr> {
  45. debug!("new() Constructor called");
  46. if password.trim().is_empty() {
  47. error!("Password is empty. You must set a password to use the wallet.");
  48. return Err(WalletEmptyPassword)
  49. }
  50. if path != "sqlite::memory:" {
  51. let p = Path::new(path.strip_prefix("sqlite://").unwrap());
  52. if let Some(dirname) = p.parent() {
  53. info!("Creating path to database: {}", dirname.display());
  54. create_dir_all(&dirname)?;
  55. }
  56. }
  57. let mut connect_opts = SqliteConnectOptions::from_str(path)?
  58. .pragma("key", password.to_string())
  59. .create_if_missing(true)
  60. .journal_mode(SqliteJournalMode::Off);
  61. connect_opts.log_statements(LevelFilter::Trace);
  62. connect_opts.log_slow_statements(LevelFilter::Trace, Duration::from_micros(10));
  63. let conn = SqlitePoolOptions::new().connect_with(connect_opts).await?;
  64. info!("Opened connection at path: {:?}", path);
  65. Ok(Arc::new(CashierDb { conn }))
  66. }
  67. pub async fn init_db(&self) -> Result<()> {
  68. let main_kps = include_str!("../../script/sql/cashier_main_keypairs.sql");
  69. let deposit_kps = include_str!("../../script/sql/cashier_deposit_keypairs.sql");
  70. let withdraw_kps = include_str!("../../script/sql/cashier_withdraw_keypairs.sql");
  71. let mut conn = self.conn.acquire().await?;
  72. debug!("Initializing main keypairs table");
  73. sqlx::query(main_kps).execute(&mut conn).await?;
  74. debug!("Initializing deposit keypairs table");
  75. sqlx::query(deposit_kps).execute(&mut conn).await?;
  76. debug!("Initializing withdraw keypairs table");
  77. sqlx::query(withdraw_kps).execute(&mut conn).await?;
  78. Ok(())
  79. }
  80. pub async fn tree_gen(&self) -> Result<()> {
  81. debug!("Attempting to generate merkle tree");
  82. let mut conn = self.conn.acquire().await?;
  83. match sqlx::query("SELECT * FROM tree").fetch_one(&mut conn).await {
  84. Ok(_) => {
  85. error!("Merkle tree already exists");
  86. Err(WalletTreeExists)
  87. }
  88. Err(_) => {
  89. let tree = BridgeTree::<MerkleNode, 32>::new(100);
  90. self.put_tree(&tree).await?;
  91. Ok(())
  92. }
  93. }
  94. }
  95. pub async fn get_tree(&self) -> Result<BridgeTree<MerkleNode, 32>> {
  96. debug!("Getting merkle tree");
  97. let mut conn = self.conn.acquire().await?;
  98. let row = sqlx::query("SELECT tree FROM tree").fetch_one(&mut conn).await?;
  99. let tree: BridgeTree<MerkleNode, 32> = bincode::deserialize(row.get("tree"))?;
  100. Ok(tree)
  101. }
  102. pub async fn put_tree(&self, tree: &BridgeTree<MerkleNode, 32>) -> Result<()> {
  103. debug!("Attempting to write merkle tree");
  104. let mut conn = self.conn.acquire().await?;
  105. let tree_bytes = bincode::serialize(tree)?;
  106. sqlx::query("INSERT INTO tree(tree) VALUES (?1)")
  107. .bind(tree_bytes)
  108. .execute(&mut conn)
  109. .await?;
  110. Ok(())
  111. }
  112. pub async fn put_main_keys(&self, token_key: &TokenKey, network: &NetworkName) -> Result<()> {
  113. debug!("Writing main keys into the database");
  114. let network = serialize(network);
  115. let mut conn = self.conn.acquire().await?;
  116. sqlx::query(
  117. "INSERT INTO main_keypairs
  118. (token_key_secret, token_key_public, network)
  119. VALUES
  120. (?1, ?2, ?3);",
  121. )
  122. .bind(token_key.secret_key.clone())
  123. .bind(token_key.public_key.clone())
  124. .bind(network)
  125. .execute(&mut conn)
  126. .await?;
  127. Ok(())
  128. }
  129. pub async fn get_main_keys(&self, network: &NetworkName) -> Result<Vec<TokenKey>> {
  130. debug!("Returning main keypairs");
  131. let network = serialize(network);
  132. let mut conn = self.conn.acquire().await?;
  133. let rows = sqlx::query(
  134. "SELECT token_key_secret, token_key_public
  135. FROM main_keypairs WHERE network = ?1;",
  136. )
  137. .bind(network)
  138. .fetch_all(&mut conn)
  139. .await?;
  140. let mut keys = vec![];
  141. for row in rows {
  142. let secret_key = row.get("token_key_secret");
  143. let public_key = row.get("token_key_public");
  144. keys.push(TokenKey { secret_key, public_key })
  145. }
  146. Ok(keys)
  147. }
  148. pub async fn remove_withdraw_and_deposit_keys(&self) -> Result<()> {
  149. debug!("Removing withdraw and deposit keys");
  150. let mut conn = self.conn.acquire().await?;
  151. sqlx::query("DROP TABLE deposit_keypairs;").execute(&mut conn).await?;
  152. sqlx::query("DROP TABLE withdraw_keypairs;").execute(&mut conn).await?;
  153. Ok(())
  154. }
  155. pub async fn put_withdraw_keys(
  156. &self,
  157. token_key_public: &[u8],
  158. d_key_public: &PublicKey,
  159. d_key_secret: &SecretKey,
  160. network: &NetworkName,
  161. token_id: &DrkTokenId,
  162. mint_address: String,
  163. ) -> Result<()> {
  164. debug!("Writing withdraw keys to database");
  165. let public = serialize(d_key_public);
  166. let secret = serialize(d_key_secret);
  167. let network = serialize(network);
  168. let token_id = serialize(token_id);
  169. let confirm = serialize(&false);
  170. let mint_address = serialize(&mint_address);
  171. let mut conn = self.conn.acquire().await?;
  172. sqlx::query(
  173. "INSERT INTO withdraw_keypairs
  174. (token_key_public, d_key_secret, d_key_public,
  175. network, token_id, mint_address, confirm)
  176. VALUES
  177. (?1, ?2, ?3, ?4, ?5, ?6, ?7);",
  178. )
  179. .bind(token_key_public)
  180. .bind(secret)
  181. .bind(public)
  182. .bind(network)
  183. .bind(token_id)
  184. .bind(mint_address)
  185. .bind(confirm)
  186. .execute(&mut conn)
  187. .await?;
  188. Ok(())
  189. }
  190. pub async fn put_deposit_keys(
  191. &self,
  192. d_key_public: &PublicKey,
  193. token_key_secret: &[u8],
  194. token_key_public: &[u8],
  195. network: &NetworkName,
  196. token_id: &DrkTokenId,
  197. mint_address: String,
  198. ) -> Result<()> {
  199. debug!("Writing deposit keys to database");
  200. let d_key_public = serialize(d_key_public);
  201. let token_id = serialize(token_id);
  202. let network = serialize(network);
  203. let confirm = serialize(&false);
  204. let mint_address = serialize(&mint_address);
  205. let mut conn = self.conn.acquire().await?;
  206. sqlx::query(
  207. "INSERT INTO deposit_keypairs
  208. (d_key_public, token_key_secret, token_key_public,
  209. network, token_id, mint_address, confirm)
  210. VALUES
  211. (?1, ?2, ?3, ?4, ?5, ?6, ?7);",
  212. )
  213. .bind(d_key_public)
  214. .bind(token_key_secret)
  215. .bind(token_key_public)
  216. .bind(network)
  217. .bind(token_id)
  218. .bind(mint_address)
  219. .bind(confirm)
  220. .execute(&mut conn)
  221. .await?;
  222. Ok(())
  223. }
  224. pub async fn get_withdraw_private_keys(&self) -> Result<Vec<SecretKey>> {
  225. debug!("Getting withdraw private keys");
  226. let confirm = serialize(&false);
  227. let mut conn = self.conn.acquire().await?;
  228. let rows = sqlx::query(
  229. "SELECT d_key_secret FROM withdraw_keypairs
  230. WHERE confirm = ?1",
  231. )
  232. .bind(confirm)
  233. .fetch_all(&mut conn)
  234. .await?;
  235. let mut secret_keys = vec![];
  236. for row in rows {
  237. let key: SecretKey = deserialize(row.get("d_key_secret"))?;
  238. secret_keys.push(key);
  239. }
  240. Ok(secret_keys)
  241. }
  242. pub async fn get_withdraw_token_public_key_by_dkey_public(
  243. &self,
  244. pubkey: &PublicKey,
  245. ) -> Result<Option<WithdrawToken>> {
  246. debug!("Get token address by pubkey");
  247. let d_key_public = serialize(pubkey);
  248. let confirm = serialize(&false);
  249. let mut conn = self.conn.acquire().await?;
  250. let rows = sqlx::query(
  251. "SELECT token_key_public, network, token_id, mint_address
  252. FROM withdraw_keypairs
  253. WHERE d_key_public = ?1
  254. AND confirm = ?2;",
  255. )
  256. .bind(d_key_public)
  257. .bind(confirm)
  258. .fetch_all(&mut conn)
  259. .await?;
  260. let mut token_addrs = vec![];
  261. for row in rows {
  262. let token_public_key = row.get("token_key_public");
  263. let network = deserialize(row.get("network"))?;
  264. let token_id = deserialize(row.get("token_id"))?;
  265. let mint_address = deserialize(row.get("mint_address"))?;
  266. token_addrs.push(WithdrawToken { token_public_key, network, token_id, mint_address });
  267. }
  268. Ok(token_addrs.pop())
  269. }
  270. pub async fn get_deposit_token_keys_by_dkey_public(
  271. &self,
  272. d_key_public: &PublicKey,
  273. network: &NetworkName,
  274. ) -> Result<Vec<TokenKey>> {
  275. debug!("Checking for existing dkey");
  276. let d_key_public = serialize(d_key_public);
  277. let network = serialize(network);
  278. let confirm = serialize(&false);
  279. let mut conn = self.conn.acquire().await?;
  280. let rows = sqlx::query(
  281. "SELECT token_key_secret, token_key_public
  282. FROM deposit_keypairs
  283. WHERE d_key_public = ?1
  284. AND network = ?2
  285. AND confirm = ?3;",
  286. )
  287. .bind(d_key_public)
  288. .bind(network)
  289. .bind(confirm)
  290. .fetch_all(&mut conn)
  291. .await?;
  292. let mut keys = vec![];
  293. for row in rows {
  294. let secret_key = row.get("token_key_secret");
  295. let public_key = row.get("token_key_public");
  296. keys.push(TokenKey { secret_key, public_key });
  297. }
  298. Ok(keys)
  299. }
  300. pub async fn get_withdraw_keys_by_token_public_key(
  301. &self,
  302. token_key_public: &[u8],
  303. network: &NetworkName,
  304. ) -> Result<Option<Keypair>> {
  305. debug!("Checking for existing token address");
  306. let confirm = serialize(&false);
  307. let network = serialize(network);
  308. let mut conn = self.conn.acquire().await?;
  309. let rows = sqlx::query(
  310. "SELECT d_key_secret, d_key_public FROM withdraw_keypairs
  311. WHERE token_key_public = ?1
  312. AND network = ?2
  313. AND confirm = ?3;",
  314. )
  315. .bind(token_key_public)
  316. .bind(network)
  317. .bind(confirm)
  318. .fetch_all(&mut conn)
  319. .await?;
  320. let mut keypairs = vec![];
  321. for row in rows {
  322. let public = deserialize(row.get("d_key_public"))?;
  323. let secret = deserialize(row.get("d_key_secret"))?;
  324. keypairs.push(Keypair { public, secret });
  325. }
  326. Ok(keypairs.pop())
  327. }
  328. pub async fn confirm_withdraw_key_record(
  329. &self,
  330. token_address: &[u8],
  331. network: &NetworkName,
  332. ) -> Result<()> {
  333. debug!("Confirm withdraw keys");
  334. let network = serialize(network);
  335. let confirm = serialize(&true);
  336. let mut conn = self.conn.acquire().await?;
  337. sqlx::query(
  338. "UPDATE withdraw_keypairs
  339. SET confirm = ?1
  340. WHERE token_key_public = ?2
  341. AND network = ?3;",
  342. )
  343. .bind(confirm)
  344. .bind(token_address)
  345. .bind(network)
  346. .execute(&mut conn)
  347. .await?;
  348. Ok(())
  349. }
  350. pub async fn confirm_deposit_key_record(
  351. &self,
  352. d_key_public: &PublicKey,
  353. network: &NetworkName,
  354. ) -> Result<()> {
  355. debug!("Confirm deposit keys");
  356. let network = serialize(network);
  357. let confirm = serialize(&true);
  358. let d_key_public = serialize(d_key_public);
  359. let mut conn = self.conn.acquire().await?;
  360. sqlx::query(
  361. "UPDATE deposit_keypairs
  362. SET confirm = ?1
  363. WHERE d_key_public = ?2
  364. AND network = ?3;",
  365. )
  366. .bind(confirm)
  367. .bind(d_key_public)
  368. .bind(network)
  369. .execute(&mut conn)
  370. .await?;
  371. Ok(())
  372. }
  373. pub async fn get_deposit_token_keys_by_network(
  374. &self,
  375. network: &NetworkName,
  376. ) -> Result<Vec<DepositToken>> {
  377. debug!("Checking for existing dkey");
  378. let network = serialize(network);
  379. let confirm = serialize(&false);
  380. let mut conn = self.conn.acquire().await?;
  381. let rows = sqlx::query(
  382. "SELECT d_key_public, token_key_secret, token_key_public, token_id, mint_address
  383. FROM deposit_keypairs
  384. WHERE network = ?1
  385. AND confirm = ?2;",
  386. )
  387. .bind(network)
  388. .bind(confirm)
  389. .fetch_all(&mut conn)
  390. .await?;
  391. let mut keys = vec![];
  392. for row in rows {
  393. let drk_public_key = deserialize(row.get("d_key_public"))?;
  394. let secret_key = row.get("token_key_secret");
  395. let public_key = row.get("token_key_public");
  396. let token_id = deserialize(row.get("token_id"))?;
  397. let mint_address = deserialize(row.get("mint_address"))?;
  398. keys.push(DepositToken {
  399. drk_public_key,
  400. token_key: TokenKey { secret_key, public_key },
  401. token_id,
  402. mint_address,
  403. });
  404. }
  405. Ok(keys)
  406. }
  407. }
  408. #[cfg(test)]
  409. mod tests {
  410. use super::*;
  411. use crate::util::serial::serialize;
  412. use group::ff::Field;
  413. use rand::rngs::OsRng;
  414. const WPASS: &str = "darkfi";
  415. #[async_std::test]
  416. async fn test_cashierdb() -> Result<()> {
  417. let wallet = CashierDb::new("sqlite::memory:", WPASS).await?;
  418. // init_db()
  419. wallet.init_db().await?;
  420. // BTC testnet address
  421. let token_addr_secret = serialize(&String::from("2222222222222222222222222222222222"));
  422. let token_addr_public = serialize(&String::from("mxVFsFW5N4mu1HPkxPttorvocvzeZ7KZyk"));
  423. let keypair = Keypair::random(&mut OsRng);
  424. let token_id = DrkTokenId::random(&mut OsRng);
  425. let network = NetworkName::Bitcoin;
  426. // put_main_keys()
  427. wallet
  428. .put_main_keys(
  429. &TokenKey {
  430. secret_key: token_addr_secret.clone(),
  431. public_key: token_addr_public.clone(),
  432. },
  433. &network,
  434. )
  435. .await?;
  436. // get_main_keys()
  437. let keys = wallet.get_main_keys(&network).await?;
  438. assert_eq!(keys.len(), 1);
  439. assert_eq!(keys[0].secret_key, token_addr_secret);
  440. assert_eq!(keys[0].public_key, token_addr_public);
  441. // put_deposit_keys()
  442. wallet
  443. .put_deposit_keys(
  444. &keypair.public,
  445. &token_addr_secret,
  446. &token_addr_public,
  447. &network,
  448. &token_id,
  449. String::new(),
  450. )
  451. .await?;
  452. // get_deposit_token_keys_by_dkey_public()
  453. let keys = wallet.get_deposit_token_keys_by_dkey_public(&keypair.public, &network).await?;
  454. assert_eq!(keys.len(), 1);
  455. assert_eq!(keys[0].secret_key, token_addr_secret);
  456. assert_eq!(keys[0].public_key, token_addr_public);
  457. // get_deposit_token_keys_by_network()
  458. let resumed_keys = wallet.get_deposit_token_keys_by_network(&network).await?;
  459. assert_eq!(resumed_keys[0].drk_public_key, keypair.public);
  460. assert_eq!(resumed_keys[0].token_key.secret_key, token_addr_secret);
  461. assert_eq!(resumed_keys[0].token_key.public_key, token_addr_public);
  462. assert_eq!(resumed_keys[0].token_id, token_id);
  463. // confirm_deposit_key_record()
  464. wallet.confirm_deposit_key_record(&keypair.public, &network).await?;
  465. let keys = wallet.get_deposit_token_keys_by_dkey_public(&keypair.public, &network).await?;
  466. assert_eq!(keys.len(), 0);
  467. // put_withdraw_keys()
  468. wallet
  469. .put_withdraw_keys(
  470. &token_addr_public,
  471. &keypair.public,
  472. &keypair.secret,
  473. &network,
  474. &token_id,
  475. String::new(),
  476. )
  477. .await?;
  478. // get_withdraw_keys_by_token_public_key()
  479. let addr =
  480. wallet.get_withdraw_keys_by_token_public_key(&token_addr_public, &network).await?;
  481. assert!(addr.is_some());
  482. // confirm_withdraw_key_record()
  483. wallet.confirm_withdraw_key_record(&token_addr_public, &network).await?;
  484. let addr =
  485. wallet.get_withdraw_keys_by_token_public_key(&token_addr_public, &network).await?;
  486. assert!(addr.is_none());
  487. Ok(())
  488. }
  489. }