walletdb.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. use crate::crypto::{coin::Coin, merkle::IncrementalWitness, merkle_node::MerkleNode, note::Note};
  2. use crate::serial;
  3. use crate::serial::{deserialize, serialize, Decodable, Encodable};
  4. use crate::util::join_config_path;
  5. use crate::{Error, Result};
  6. use async_std::sync::{Arc, Mutex};
  7. use ff::Field;
  8. use log::*;
  9. use rand::rngs::OsRng;
  10. use rusqlite::{named_params, params, Connection};
  11. use std::path::PathBuf;
  12. pub type WalletPtr = Arc<WalletDB>;
  13. pub struct WalletDB {
  14. pub path: PathBuf,
  15. pub secrets: Vec<jubjub::Fr>,
  16. pub cashier_secrets: Vec<jubjub::Fr>,
  17. pub coins: Mutex<Vec<Coin>>,
  18. pub notes: Mutex<Vec<Note>>,
  19. pub witnesses: Mutex<Vec<IncrementalWitness<MerkleNode>>>,
  20. pub cashier_public: jubjub::SubgroupPoint,
  21. pub public: jubjub::SubgroupPoint,
  22. pub password: String,
  23. }
  24. impl WalletDB {
  25. pub fn new(wallet: &str, password: String) -> Result<Self> {
  26. debug!(target: "walletdb", "new() Constructor called");
  27. let path = join_config_path(&PathBuf::from(wallet))?;
  28. let cashier_secret = jubjub::Fr::random(&mut OsRng);
  29. let secret = jubjub::Fr::random(&mut OsRng);
  30. let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
  31. let cashier_public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * cashier_secret;
  32. let coins = Mutex::new(Vec::new());
  33. let notes = Mutex::new(Vec::new());
  34. let witnesses = Mutex::new(Vec::new());
  35. Ok(Self {
  36. path,
  37. cashier_secrets: vec![cashier_secret.clone()],
  38. secrets: vec![secret.clone()],
  39. cashier_public,
  40. public,
  41. coins,
  42. notes,
  43. witnesses,
  44. password,
  45. //conn,
  46. })
  47. }
  48. pub fn init_db(&self) -> Result<()> {
  49. if !self.password.trim().is_empty() {
  50. let contents = include_str!("../../res/schema.sql");
  51. let conn = Connection::open(&self.path)?;
  52. debug!(target: "walletdb", "OPENED CONNECTION AT PATH {:?}", self.path);
  53. //conn.execute("PRAGMA key=(?1)", params![self.password])?;
  54. conn.execute_batch(&contents)?
  55. } else {
  56. println!("Password is empty. You must set a password to use the wallet.");
  57. println!("Current password: {}", self.password);
  58. return Err(Error::EmptyPassword);
  59. }
  60. Ok(())
  61. }
  62. pub fn init_cashier_db(&self) -> Result<()> {
  63. let conn = Connection::open(&self.path)?;
  64. debug!(target: "walletdb", "OPENED CONNECTION AT PATH {:?}", self.path);
  65. let contents = include_str!("../../res/schema.sql");
  66. conn.execute_batch(&contents)?;
  67. Ok(())
  68. }
  69. pub fn put_own_coins(
  70. &self,
  71. coin: Coin,
  72. note: Note,
  73. witness: IncrementalWitness<MerkleNode>,
  74. secret: jubjub::Fr,
  75. ) -> Result<()> {
  76. // prepare the values
  77. let coin = self.get_value_serialized(&coin.repr)?;
  78. let serial = self.get_value_serialized(&note.serial)?;
  79. let coin_blind = self.get_value_serialized(&note.coin_blind)?;
  80. let valcom_blind = self.get_value_serialized(&note.valcom_blind)?;
  81. let value = self.get_value_serialized(&note.value)?;
  82. let asset_id = self.get_value_serialized(&note.asset_id)?;
  83. let witness = self.get_value_serialized(&witness)?;
  84. let secret = self.get_value_serialized(&secret)?;
  85. // open connection
  86. let conn = Connection::open(&self.path)?;
  87. // unlock database
  88. conn.execute("PRAGMA key=(?1)", params![self.password])?;
  89. // return key_id from key_private
  90. let mut get_id =
  91. conn.prepare("SELECT key_id FROM keys WHERE key_private = :key_private")?;
  92. let rows = get_id.query_map::<u8, _, _>(&[(":key_private", &secret)], |row| row.get(0))?;
  93. let mut key_id = Vec::new();
  94. for id in rows {
  95. key_id.push(id?)
  96. }
  97. conn.execute(
  98. "INSERT INTO coins(coin, serial, value, asset_id, coin_blind, valcom_blind, witness, key_id)
  99. VALUES (:coin, :serial, :value, :asset_id, :coin_blind, :valcom_blind, :witness, :key_id)",
  100. named_params! {
  101. ":coin": coin,
  102. ":serial": serial,
  103. ":value": value,
  104. ":asset_id": asset_id,
  105. ":coin_blind": coin_blind,
  106. ":valcom_blind": valcom_blind,
  107. ":witness": witness,
  108. ":key_id": key_id.pop().expect("key_id not found!"),
  109. },
  110. )?;
  111. Ok(())
  112. }
  113. pub fn key_gen(&self) -> (Vec<u8>, Vec<u8>) {
  114. debug!(target: "key_gen", "Attempting to generate keys...");
  115. let secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  116. let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
  117. let pubkey = serial::serialize(&public);
  118. let privkey = serial::serialize(&secret);
  119. (pubkey, privkey)
  120. }
  121. pub fn cash_key_gen(&self) -> (Vec<u8>, Vec<u8>) {
  122. debug!(target: "cash key_gen", "Generating cashier keys...");
  123. let secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  124. let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
  125. let pubkey = serial::serialize(&public);
  126. let privkey = serial::serialize(&secret);
  127. (pubkey, privkey)
  128. }
  129. pub fn put_keypair(&self, key_public: Vec<u8>, key_private: Vec<u8>) -> Result<()> {
  130. let conn = Connection::open(&self.path)?;
  131. println!("{}", self.password);
  132. conn.execute("PRAGMA key=(?1)", params![self.password])?;
  133. conn.execute(
  134. "INSERT INTO keys(key_public, key_private) VALUES (?1, ?2)",
  135. params![key_public, key_private],
  136. )?;
  137. Ok(())
  138. }
  139. pub fn put_cashier_pub(&self, key_public: Vec<u8>) -> Result<()> {
  140. debug!(target: "save_cash_key", "Save cashier keys...");
  141. let conn = Connection::open(&self.path)?;
  142. conn.execute("PRAGMA key=(?1)", params![self.password])?;
  143. conn.execute(
  144. "INSERT INTO cashier(key_public) VALUES (?1)",
  145. params![key_public],
  146. )?;
  147. Ok(())
  148. }
  149. pub fn get_public(&self) -> Result<Vec<u8>> {
  150. debug!(target: "get", "Returning keys...");
  151. let conn = Connection::open(&self.path)?;
  152. conn.execute("PRAGMA key=(?1)", params![self.password])?;
  153. let mut stmt = conn.prepare("SELECT key_public FROM keys")?;
  154. let key_iter = stmt.query_map::<u8, _, _>([], |row| row.get(0))?;
  155. let mut pub_keys = Vec::new();
  156. for key in key_iter {
  157. pub_keys.push(key?);
  158. }
  159. Ok(pub_keys)
  160. }
  161. pub fn get_cashier_public(&self) -> Result<Vec<u8>> {
  162. debug!(target: "get_cashier_public", "Returning keys...");
  163. let conn = Connection::open(&self.path)?;
  164. conn.execute("PRAGMA key=(?1)", params![self.password])?;
  165. let mut stmt = conn.prepare("SELECT key_public FROM cashier")?;
  166. let key_iter = stmt.query_map::<u8, _, _>([], |row| row.get(0))?;
  167. let mut pub_keys = Vec::new();
  168. for key in key_iter {
  169. pub_keys.push(key?);
  170. }
  171. Ok(pub_keys)
  172. }
  173. pub fn get_private(&self) -> Result<Vec<u8>> {
  174. debug!(target: "get", "Returning keys...");
  175. let conn = Connection::open(&self.path)?;
  176. conn.execute("PRAGMA key=(?1)", params![self.password])?;
  177. let mut stmt = conn.prepare("SELECT key_private FROM keys")?;
  178. let key_iter = stmt.query_map::<u8, _, _>([], |row| row.get(0))?;
  179. let mut keys = Vec::new();
  180. for key in key_iter {
  181. keys.push(key?);
  182. }
  183. Ok(keys)
  184. }
  185. pub fn test_wallet(&self) -> Result<()> {
  186. let conn = Connection::open(&self.path)?;
  187. conn.execute("PRAGMA key=(?1)", params![self.password])?;
  188. let mut stmt = conn.prepare("SELECT * FROM keys")?;
  189. let _rows = stmt.query([])?;
  190. Ok(())
  191. }
  192. pub fn get_value_serialized<T: Encodable>(&self, data: &T) -> Result<Vec<u8>> {
  193. let v = serialize(data);
  194. Ok(v)
  195. }
  196. pub fn get_value_deserialized<D: Decodable>(&self, key: Vec<u8>) -> Result<D> {
  197. let v: D = deserialize(&key)?;
  198. Ok(v)
  199. }
  200. }
  201. #[cfg(test)]
  202. mod tests {
  203. use super::*;
  204. #[test]
  205. pub fn test_unlock() -> Result<()> {
  206. let password = "roseiscool2021";
  207. let path = join_config_path(&PathBuf::from("wallet.db"))?;
  208. let contents = include_str!("../../res/schema.sql");
  209. let conn = Connection::open(&path)?;
  210. debug!(target: "walletdb", "OPENED CONNECTION AT PATH {:?}", path);
  211. conn.execute("PRAGMA key=(?1)", params![password])?;
  212. conn.execute_batch(&contents)?;
  213. Ok(())
  214. }
  215. //#[test]
  216. //pub fn test_keypair() -> Result<()> {
  217. // let path = join_config_path(&PathBuf::from("wallet.db"))?;
  218. // let conn = Connection::open(path)?;
  219. // let secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  220. // let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
  221. // let key_public = serial::serialize(&public);
  222. // let key_private = serial::serialize(&secret);
  223. // let mut stmt = conn.prepare("PRAGMA key = 'testkey'")?;
  224. // let _rows = stmt.query([])?;
  225. // conn.execute(
  226. // "INSERT INTO keys(key_public, key_private) VALUES (?1, ?2)",
  227. // params![key_public, key_private],
  228. // )?;
  229. // Ok(())
  230. //}
  231. //#[test]
  232. //pub fn test_get_id() -> Result<()> {
  233. // let path = join_config_path(&PathBuf::from("wallet.db"))?;
  234. // let conn = Connection::open(path)?;
  235. // let secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  236. // let key_private = serial::serialize(&secret);
  237. // let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
  238. // let key_public = serial::serialize(&public);
  239. // let mut stmt = conn.prepare("PRAGMA key = 'testkey'")?;
  240. // let _rows = stmt.query([])?;
  241. // conn.execute(
  242. // "INSERT INTO keys(key_public, key_private) VALUES (?1, ?2)",
  243. // params![key_public, key_private],
  244. // )?;
  245. // let mut get_id =
  246. // conn.prepare("SELECT key_id FROM keys WHERE key_private = :key_private")?;
  247. // let rows =
  248. // get_id.query_map::<u8, _, _>(&[(":key_private", &key_private)], |row| row.get(0))?;
  249. // let mut key_id = Vec::new();
  250. // for id in rows {
  251. // key_id.push(id?)
  252. // }
  253. // println!("FOUND ID: {:?}", key_id.pop().unwrap());
  254. // Ok(())
  255. //}
  256. //#[test]
  257. //pub fn test_own_coins() -> Result<()> {
  258. // let key_private = Vec::new();
  259. // let coin = Vec::new();
  260. // let serial = Vec::new();
  261. // let coin_blind = Vec::new();
  262. // let valcom_blind = Vec::new();
  263. // let value = Vec::new();
  264. // let asset_id = Vec::new();
  265. // let witness = Vec::new();
  266. // let path = join_config_path(&PathBuf::from("wallet.db"))?;
  267. // let conn = Connection::open(path)?;
  268. // let contents = include_str!("../../res/schema.sql");
  269. // match conn.execute_batch(&contents) {
  270. // Ok(v) => println!("Database initalized successfully {:?}", v),
  271. // Err(err) => println!("Error: {}", err),
  272. // };
  273. // //let mut unlock = conn.prepare("PRAGMA key = 'testkey'")?;
  274. // //let _rows = unlock.query([])?;
  275. // let mut get_id =
  276. // conn.prepare("SELECT key_id FROM keys WHERE key_private = :key_private")?;
  277. // let rows =
  278. // get_id.query_map::<u8, _, _>(&[(":key_private", &key_private)], |row| row.get(0))?;
  279. // let mut key_id = Vec::new();
  280. // for id in rows {
  281. // key_id.push(id?)
  282. // }
  283. // conn.execute(
  284. // "INSERT INTO coins(coin, serial, value, asset_id, coin_blind, valcom_blind, witness, key_id)
  285. // VALUES (:coin, :serial, :value, :asset_id, :coin_blind, :valcom_blind, :witness, :key_id)",
  286. // named_params! {
  287. // ":coin": coin,
  288. // ":serial": serial,
  289. // ":value": value,
  290. // ":asset_id": asset_id,
  291. // ":coin_blind": coin_blind,
  292. // ":valcom_blind": valcom_blind,
  293. // ":witness": witness,
  294. // ":key_id": key_id.pop().expect("key_id not found!"),
  295. // },
  296. // )?;
  297. // Ok(())
  298. //}
  299. }