walletdb.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. use super::WalletApi;
  2. use crate::client::ClientFailed;
  3. use crate::crypto::{
  4. merkle::IncrementalWitness, merkle_node::MerkleNode, note::Note, OwnCoin, OwnCoins,
  5. };
  6. use crate::serial;
  7. use crate::{Error, Result};
  8. use async_std::sync::Arc;
  9. use ff::Field;
  10. use log::*;
  11. use rand::rngs::OsRng;
  12. use rusqlite::{named_params, params, Connection};
  13. use std::path::PathBuf;
  14. pub type WalletPtr = Arc<WalletDb>;
  15. #[derive(Debug, Clone)]
  16. pub struct Keypair {
  17. pub public: jubjub::SubgroupPoint,
  18. pub private: jubjub::Fr,
  19. }
  20. pub struct WalletDb {
  21. pub path: PathBuf,
  22. pub password: String,
  23. }
  24. impl WalletApi for WalletDb {
  25. fn get_password(&self) -> String {
  26. self.password.to_owned()
  27. }
  28. fn get_path(&self) -> PathBuf {
  29. self.path.to_owned()
  30. }
  31. }
  32. impl WalletDb {
  33. pub fn new(path: &PathBuf, password: String) -> Result<WalletPtr> {
  34. debug!(target: "WALLETDB", "new() Constructor called");
  35. Ok(Arc::new(Self {
  36. path: path.to_owned(),
  37. password,
  38. }))
  39. }
  40. pub fn init_db(&self) -> Result<()> {
  41. if !self.password.trim().is_empty() {
  42. let contents = include_str!("../../sql/schema.sql");
  43. let conn = Connection::open(&self.path)?;
  44. debug!(target: "WALLETDB", "OPENED CONNECTION AT PATH {:?}", self.path);
  45. conn.pragma_update(None, "key", &self.password)?;
  46. conn.execute_batch(&contents)?;
  47. } else {
  48. debug!(target: "WALLETDB", "Password is empty. You must set a password to use the wallet.");
  49. return Err(Error::from(ClientFailed::EmptyPassword));
  50. }
  51. Ok(())
  52. }
  53. pub fn key_gen(&self) -> Result<(Vec<u8>, Vec<u8>)> {
  54. debug!(target: "WALLETDB", "Attempting to generate keys...");
  55. let secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  56. let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
  57. let pubkey = serial::serialize(&public);
  58. let privkey = serial::serialize(&secret);
  59. self.put_keypair(pubkey.clone(), privkey.clone())?;
  60. Ok((pubkey, privkey))
  61. }
  62. pub fn put_keypair(&self, key_public: Vec<u8>, key_private: Vec<u8>) -> Result<()> {
  63. let conn = Connection::open(&self.path)?;
  64. conn.pragma_update(None, "key", &self.password)?;
  65. conn.execute(
  66. "INSERT INTO keys(key_public, key_private) VALUES (?1, ?2)",
  67. params![key_public, key_private],
  68. )?;
  69. Ok(())
  70. }
  71. pub fn get_keypairs(&self) -> Result<Vec<Keypair>> {
  72. debug!(target: "WALLETDB", "Returning keys...");
  73. let conn = Connection::open(&self.path)?;
  74. conn.pragma_update(None, "key", &self.password)?;
  75. let mut stmt = conn.prepare("SELECT * FROM keys")?;
  76. // this just gets the first key. maybe we should randomize this
  77. let key_iter = stmt.query_map([], |row| Ok((row.get(1)?, row.get(2)?)))?;
  78. let mut keypairs = Vec::new();
  79. for key in key_iter {
  80. let key = key?;
  81. let public = key.0;
  82. let private = key.1;
  83. let public: jubjub::SubgroupPoint =
  84. self.get_value_deserialized::<jubjub::SubgroupPoint>(public)?;
  85. let private: jubjub::Fr = self.get_value_deserialized::<jubjub::Fr>(private)?;
  86. keypairs.push(Keypair { public, private });
  87. }
  88. if keypairs.is_empty() {
  89. return Err(Error::from(ClientFailed::DoNotHaveKeypair));
  90. }
  91. Ok(keypairs)
  92. }
  93. pub fn get_own_coins(&self) -> Result<OwnCoins> {
  94. // open connection
  95. let conn = Connection::open(&self.path)?;
  96. // unlock database
  97. conn.pragma_update(None, "key", &self.password)?;
  98. let mut coins = conn.prepare("SELECT * FROM coins")?;
  99. let rows = coins.query_map([], |row| {
  100. let coin = self.get_value_deserialized(row.get(1)?).unwrap();
  101. // note
  102. let serial = self.get_value_deserialized(row.get(2)?).unwrap();
  103. let coin_blind = self.get_value_deserialized(row.get(3)?).unwrap();
  104. let valcom_blind = self.get_value_deserialized(row.get(4)?).unwrap();
  105. let value: u64 = row.get(5)?;
  106. let asset_id = self.get_value_deserialized(row.get(6)?).unwrap();
  107. let note = Note {
  108. serial,
  109. value,
  110. asset_id,
  111. coin_blind,
  112. valcom_blind,
  113. };
  114. let witness = self.get_value_deserialized(row.get(7)?).unwrap();
  115. let key_id: u64 = row.get(8)?;
  116. // return key_private from key_id
  117. let mut get_private_key =
  118. conn.prepare("SELECT key_private FROM keys WHERE key_id = :key_id")?;
  119. let rows = get_private_key.query_map(&[(":key_id", &key_id)], |row| row.get(0))?;
  120. let mut secret = Vec::new();
  121. for id in rows {
  122. secret.push(id?)
  123. }
  124. let secret: jubjub::Fr = self
  125. .get_value_deserialized(secret.pop().expect("Load public_key from walletdb"))
  126. .unwrap();
  127. Ok(OwnCoin {
  128. coin,
  129. note,
  130. secret,
  131. witness,
  132. })
  133. })?;
  134. let mut own_coins = Vec::new();
  135. for id in rows {
  136. own_coins.push(id?)
  137. }
  138. Ok(own_coins)
  139. }
  140. pub fn put_own_coins(&self, own_coin: OwnCoin) -> Result<()> {
  141. // prepare the values
  142. let coin = self.get_value_serialized(&own_coin.coin.repr)?;
  143. let serial = self.get_value_serialized(&own_coin.note.serial)?;
  144. let coin_blind = self.get_value_serialized(&own_coin.note.coin_blind)?;
  145. let valcom_blind = self.get_value_serialized(&own_coin.note.valcom_blind)?;
  146. let value: u64 = own_coin.note.value;
  147. let asset_id = self.get_value_serialized(&own_coin.note.asset_id)?;
  148. let witness = self.get_value_serialized(&own_coin.witness)?;
  149. let secret = self.get_value_serialized(&own_coin.secret)?;
  150. // open connection
  151. let conn = Connection::open(&self.path)?;
  152. // unlock database
  153. conn.pragma_update(None, "key", &self.password)?;
  154. // return key_id from key_private
  155. let mut get_id =
  156. conn.prepare("SELECT key_id FROM keys WHERE key_private = :key_private")?;
  157. let rows = get_id.query_map::<u64, _, _>(&[(":key_private", &secret)], |row| row.get(0))?;
  158. let mut key_id = Vec::new();
  159. for id in rows {
  160. key_id.push(id?)
  161. }
  162. conn.execute(
  163. "INSERT INTO coins(coin, serial, value, asset_id, coin_blind, valcom_blind, witness, key_id)
  164. VALUES (:coin, :serial, :value, :asset_id, :coin_blind, :valcom_blind, :witness, :key_id)",
  165. named_params! {
  166. ":coin": coin,
  167. ":serial": serial,
  168. ":value": value,
  169. ":asset_id": asset_id,
  170. ":coin_blind": coin_blind,
  171. ":valcom_blind": valcom_blind,
  172. ":witness": witness,
  173. ":key_id": key_id.pop().expect("Get key_id"),
  174. },
  175. )?;
  176. Ok(())
  177. }
  178. pub fn get_witnesses(&self) -> Result<Vec<(u64, IncrementalWitness<MerkleNode>)>> {
  179. let conn = Connection::open(&self.path)?;
  180. conn.pragma_update(None, "key", &self.password)?;
  181. let mut witnesses = conn.prepare("SELECT coin_id, witness FROM coins;")?;
  182. let rows = witnesses.query_map([], |row| {
  183. let coin_id: u64 = row.get(0)?;
  184. let witness: IncrementalWitness<MerkleNode> =
  185. self.get_value_deserialized(row.get(1)?).unwrap();
  186. Ok((coin_id, witness))
  187. })?;
  188. let mut witnesses = Vec::new();
  189. for i in rows {
  190. witnesses.push(i?)
  191. }
  192. Ok(witnesses)
  193. }
  194. pub fn update_witness(
  195. &self,
  196. coin_id: u64,
  197. witness: IncrementalWitness<MerkleNode>,
  198. ) -> Result<()> {
  199. let conn = Connection::open(&self.path)?;
  200. conn.pragma_update(None, "key", &self.password)?;
  201. let witness = self.get_value_serialized(&witness)?;
  202. conn.execute(
  203. "UPDATE coins SET witness = ?1 WHERE coin_id = ?2;",
  204. params![witness, coin_id],
  205. )?;
  206. Ok(())
  207. }
  208. pub fn put_cashier_pub(&self, key_public: Vec<u8>) -> Result<()> {
  209. debug!(target: "WALLETDB", "Save cashier keys...");
  210. let conn = Connection::open(&self.path)?;
  211. conn.pragma_update(None, "key", &self.password)?;
  212. conn.execute(
  213. "INSERT INTO cashier(key_public) VALUES (?1)",
  214. params![key_public],
  215. )?;
  216. Ok(())
  217. }
  218. pub fn get_cashier_public_keys(&self) -> Result<Vec<jubjub::SubgroupPoint>> {
  219. debug!(target: "WALLETDB", "Returning keys...");
  220. let conn = Connection::open(&self.path)?;
  221. conn.pragma_update(None, "key", &self.password)?;
  222. let mut stmt = conn.prepare("SELECT key_public FROM cashier")?;
  223. let key_iter = stmt.query_map([], |row| row.get(0))?;
  224. let mut pub_keys = Vec::new();
  225. for key in key_iter {
  226. let public: jubjub::SubgroupPoint = self.get_value_deserialized(key?)?;
  227. pub_keys.push(public);
  228. }
  229. if pub_keys.is_empty() {
  230. return Err(Error::from(ClientFailed::DoNotHaveCashierPublicKey));
  231. }
  232. Ok(pub_keys)
  233. }
  234. pub fn test_wallet(&self) -> Result<()> {
  235. let conn = Connection::open(&self.path)?;
  236. conn.pragma_update(None, "key", &self.password)?;
  237. let mut stmt = conn.prepare("SELECT * FROM keys")?;
  238. let _rows = stmt.query([])?;
  239. Ok(())
  240. }
  241. }
  242. #[cfg(test)]
  243. mod tests {
  244. use super::*;
  245. use crate::crypto::{coin::Coin, OwnCoin};
  246. use crate::util::join_config_path;
  247. use ff::PrimeField;
  248. #[test]
  249. pub fn test_save_and_load_keypair() -> Result<()> {
  250. let walletdb_path = join_config_path(&PathBuf::from("test_wallet.db"))?;
  251. let wallet = WalletDb::new(&walletdb_path, "darkfi".into())?;
  252. wallet.init_db()?;
  253. let secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  254. let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
  255. let key_public = serial::serialize(&public);
  256. let key_private = serial::serialize(&secret);
  257. wallet.put_keypair(key_public, key_private)?;
  258. let keypair = wallet.get_keypairs()?[0].clone();
  259. assert_eq!(public, keypair.public);
  260. assert_eq!(secret, keypair.private);
  261. wallet.destroy()?;
  262. Ok(())
  263. }
  264. #[test]
  265. pub fn test_put_and_get_own_coins() -> Result<()> {
  266. let walletdb_path = join_config_path(&PathBuf::from("test2_wallet.db"))?;
  267. let wallet = WalletDb::new(&walletdb_path, "darkfi".into())?;
  268. wallet.init_db()?;
  269. let secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  270. let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
  271. let key_public = serial::serialize(&public);
  272. let key_private = serial::serialize(&secret);
  273. wallet.put_keypair(key_public, key_private)?;
  274. let note = Note {
  275. serial: jubjub::Fr::random(&mut OsRng),
  276. value: 110,
  277. asset_id: jubjub::Fr::random(&mut OsRng),
  278. coin_blind: jubjub::Fr::random(&mut OsRng),
  279. valcom_blind: jubjub::Fr::random(&mut OsRng),
  280. };
  281. let coin = Coin::new(bls12_381::Scalar::random(&mut OsRng).to_repr());
  282. let mut tree = crate::crypto::merkle::CommitmentTree::empty();
  283. tree.append(MerkleNode::from_coin(&coin))?;
  284. let witness = IncrementalWitness::from_tree(&tree);
  285. let own_coin = OwnCoin {
  286. coin,
  287. note: note.clone(),
  288. secret,
  289. witness: witness.clone(),
  290. };
  291. wallet.put_own_coins(own_coin.clone())?;
  292. let own_coin = wallet.get_own_coins()?[0].clone();
  293. assert_eq!(&own_coin.note.valcom_blind, &note.valcom_blind);
  294. assert_eq!(&own_coin.note.coin_blind, &note.coin_blind);
  295. assert_eq!(own_coin.secret, secret);
  296. assert_eq!(own_coin.witness.root(), witness.root());
  297. assert_eq!(own_coin.witness.path(), witness.path());
  298. wallet.destroy()?;
  299. Ok(())
  300. }
  301. #[test]
  302. pub fn test_get_witnesses_and_update_them() -> Result<()> {
  303. let walletdb_path = join_config_path(&PathBuf::from("test3_wallet.db"))?;
  304. let wallet = WalletDb::new(&walletdb_path, "darkfi".into())?;
  305. wallet.init_db()?;
  306. let secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  307. let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
  308. let key_public = serial::serialize(&public);
  309. let key_private = serial::serialize(&secret);
  310. wallet.put_keypair(key_public, key_private)?;
  311. let mut tree = crate::crypto::merkle::CommitmentTree::empty();
  312. let note = Note {
  313. serial: jubjub::Fr::random(&mut OsRng),
  314. value: 110,
  315. asset_id: jubjub::Fr::random(&mut OsRng),
  316. coin_blind: jubjub::Fr::random(&mut OsRng),
  317. valcom_blind: jubjub::Fr::random(&mut OsRng),
  318. };
  319. let coin = Coin::new(bls12_381::Scalar::random(&mut OsRng).to_repr());
  320. let node = MerkleNode::from_coin(&coin);
  321. tree.append(node)?;
  322. tree.append(node)?;
  323. tree.append(node)?;
  324. tree.append(node)?;
  325. let witness = IncrementalWitness::from_tree(&tree);
  326. let own_coin = OwnCoin {
  327. coin,
  328. note,
  329. secret,
  330. witness,
  331. };
  332. wallet.put_own_coins(own_coin.clone())?;
  333. wallet.put_own_coins(own_coin.clone())?;
  334. wallet.put_own_coins(own_coin.clone())?;
  335. wallet.put_own_coins(own_coin.clone())?;
  336. let coin2 = Coin::new(bls12_381::Scalar::random(&mut OsRng).to_repr());
  337. let node2 = MerkleNode::from_coin(&coin2);
  338. tree.append(node2)?;
  339. for (coin_id, witness) in wallet.get_witnesses()?.iter_mut() {
  340. witness.append(node2).expect("Append to witness");
  341. wallet.update_witness(coin_id.clone(), witness.clone())?;
  342. }
  343. for (_, witness) in wallet.get_witnesses()?.iter() {
  344. assert_eq!(tree.root(), witness.root());
  345. }
  346. wallet.destroy()?;
  347. Ok(())
  348. }
  349. }