cashierdb.rs 18 KB

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