client.rs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. use async_std::sync::{Arc, Mutex};
  2. use bellman::groth16;
  3. use bls12_381::Bls12;
  4. use log::*;
  5. use std::net::SocketAddr;
  6. use std::path::PathBuf;
  7. use crate::{
  8. blockchain::{rocks::columns, Rocks, RocksColumn, Slab},
  9. crypto::{
  10. load_params,
  11. merkle::{CommitmentTree, IncrementalWitness},
  12. merkle_node::MerkleNode,
  13. note::{EncryptedNote, Note},
  14. nullifier::Nullifier,
  15. save_params, setup_mint_prover, setup_spend_prover, OwnCoin,
  16. },
  17. serial::{Decodable, Encodable},
  18. service::{GatewayClient, GatewaySlabsSubscriber},
  19. state::{state_transition, ProgramState, StateUpdate},
  20. tx,
  21. wallet::{CashierDbPtr, Keypair, WalletPtr},
  22. Result,
  23. };
  24. #[derive(Debug)]
  25. pub enum ClientFailed {
  26. NotEnoughValue(u64),
  27. InvalidAddress(String),
  28. InvalidAmount(u64),
  29. UnableToGetDepositAddress,
  30. UnableToGetWithdrawAddress,
  31. DoesNotHaveCashierPublicKey,
  32. DoesNotHaveKeypair,
  33. EmptyPassword,
  34. WalletInitialized,
  35. KeyExists,
  36. ClientError(String),
  37. }
  38. pub struct Client {
  39. pub state: Arc<Mutex<State>>,
  40. mint_params: bellman::groth16::Parameters<Bls12>,
  41. spend_params: bellman::groth16::Parameters<Bls12>,
  42. gateway: GatewayClient,
  43. pub main_keypair: Keypair,
  44. }
  45. impl Client {
  46. pub async fn new(
  47. rocks: Arc<Rocks>,
  48. gateway_addrs: (SocketAddr, SocketAddr),
  49. params_paths: (PathBuf, PathBuf),
  50. wallet: WalletPtr,
  51. ) -> Result<Self> {
  52. let slabstore = RocksColumn::<columns::Slabs>::new(rocks.clone());
  53. let merkle_roots = RocksColumn::<columns::MerkleRoots>::new(rocks.clone());
  54. let nullifiers = RocksColumn::<columns::Nullifiers>::new(rocks);
  55. let mint_params_path = params_paths.0.to_str().unwrap_or("mint.params");
  56. let spend_params_path = params_paths.1.to_str().unwrap_or("spend.params");
  57. wallet.init_db().await?;
  58. if wallet.get_keypairs()?.is_empty() {
  59. wallet.key_gen()?;
  60. }
  61. let main_keypair = wallet.get_keypairs()?[0].clone();
  62. // Auto create trusted ceremony parameters if they don't exist
  63. if !params_paths.0.exists() {
  64. let params = setup_mint_prover();
  65. save_params(mint_params_path, &params)?;
  66. }
  67. if !params_paths.1.exists() {
  68. let params = setup_spend_prover();
  69. save_params(spend_params_path, &params)?;
  70. }
  71. // Load trusted setup parameters
  72. let (mint_params, mint_pvk) = load_params(mint_params_path)?;
  73. let (spend_params, spend_pvk) = load_params(spend_params_path)?;
  74. let state = Arc::new(Mutex::new(State {
  75. tree: CommitmentTree::empty(),
  76. merkle_roots,
  77. nullifiers,
  78. mint_pvk,
  79. spend_pvk,
  80. wallet,
  81. }));
  82. // create gateway client
  83. debug!(target: "CLIENT", "Creating GatewayClient");
  84. let gateway = GatewayClient::new(gateway_addrs.0, gateway_addrs.1, slabstore)?;
  85. Ok(Self {
  86. state,
  87. mint_params,
  88. spend_params,
  89. gateway,
  90. main_keypair,
  91. })
  92. }
  93. pub async fn start(&mut self) -> Result<()> {
  94. self.gateway.start().await?;
  95. Ok(())
  96. }
  97. pub async fn transfer(
  98. &mut self,
  99. token_id: jubjub::Fr,
  100. pub_key: jubjub::SubgroupPoint,
  101. amount: u64,
  102. ) -> ClientResult<()> {
  103. debug!(target: "CLIENT", "Start transfer {}", amount);
  104. if amount == 0 {
  105. return Err(ClientFailed::InvalidAmount(amount as u64).into());
  106. }
  107. let token_id_exists = self.state.lock().await.wallet.token_id_exists(&token_id)?;
  108. if token_id_exists {
  109. self.send(pub_key, amount, token_id, false).await?;
  110. } else {
  111. return Err(ClientFailed::NotEnoughValue(amount));
  112. }
  113. debug!(target: "CLIENT", "End transfer {}", amount);
  114. Ok(())
  115. }
  116. pub async fn send(
  117. &mut self,
  118. pub_key: jubjub::SubgroupPoint,
  119. amount: u64,
  120. asset_id: jubjub::Fr,
  121. clear_input: bool,
  122. ) -> ClientResult<()> {
  123. debug!(target: "CLIENT", "Start send {}", amount);
  124. let slab = self
  125. .build_slab_from_tx(pub_key, amount, asset_id, clear_input)
  126. .await?;
  127. self.gateway.put_slab(slab).await?;
  128. debug!(target: "CLIENT", "End send {}", amount);
  129. Ok(())
  130. }
  131. async fn build_slab_from_tx(
  132. &self,
  133. pub_key: jubjub::SubgroupPoint,
  134. value: u64,
  135. asset_id: jubjub::Fr,
  136. clear_input: bool,
  137. ) -> Result<Slab> {
  138. debug!(target: "CLIENT", "Start build slab from tx");
  139. let mut clear_inputs: Vec<tx::TransactionBuilderClearInputInfo> = vec![];
  140. let mut inputs: Vec<tx::TransactionBuilderInputInfo> = vec![];
  141. let mut outputs: Vec<tx::TransactionBuilderOutputInfo> = vec![];
  142. if clear_input {
  143. let signature_secret = self.main_keypair.private;
  144. let input = tx::TransactionBuilderClearInputInfo {
  145. value,
  146. asset_id,
  147. signature_secret,
  148. };
  149. clear_inputs.push(input);
  150. } else {
  151. inputs = self.build_inputs(value, asset_id, &mut outputs).await?;
  152. }
  153. outputs.push(tx::TransactionBuilderOutputInfo {
  154. value,
  155. asset_id,
  156. public: pub_key,
  157. });
  158. let builder = tx::TransactionBuilder {
  159. clear_inputs,
  160. inputs,
  161. outputs,
  162. };
  163. let mut tx_data = vec![];
  164. {
  165. let tx = builder.build(&self.mint_params, &self.spend_params);
  166. tx.encode(&mut tx_data).expect("encode tx");
  167. }
  168. let slab = Slab::new(tx_data);
  169. debug!(target: "CLIENT", "End build slab from tx");
  170. Ok(slab)
  171. }
  172. async fn build_inputs(
  173. &self,
  174. amount: u64,
  175. asset_id: jubjub::Fr,
  176. outputs: &mut Vec<tx::TransactionBuilderOutputInfo>,
  177. ) -> Result<Vec<tx::TransactionBuilderInputInfo>> {
  178. debug!(target: "CLIENT", "Start build inputs");
  179. let mut inputs: Vec<tx::TransactionBuilderInputInfo> = vec![];
  180. let mut inputs_value: u64 = 0;
  181. let own_coins = self.state.lock().await.wallet.get_own_coins()?;
  182. for own_coin in own_coins.iter() {
  183. if inputs_value >= amount {
  184. break;
  185. }
  186. let witness = &own_coin.witness;
  187. let merkle_path = witness.path().unwrap();
  188. inputs_value += own_coin.note.value;
  189. let input = tx::TransactionBuilderInputInfo {
  190. merkle_path,
  191. secret: own_coin.secret,
  192. note: own_coin.note.clone(),
  193. };
  194. inputs.push(input);
  195. }
  196. if inputs_value < amount {
  197. return Err(ClientFailed::NotEnoughValue(inputs_value).into());
  198. }
  199. if inputs_value > amount {
  200. let inputs_len = inputs.len();
  201. let input = &inputs[inputs_len - 1];
  202. let return_value: u64 = inputs_value - amount;
  203. let own_pub_key = zcash_primitives::constants::SPENDING_KEY_GENERATOR * input.secret;
  204. outputs.push(tx::TransactionBuilderOutputInfo {
  205. value: return_value,
  206. asset_id,
  207. public: own_pub_key,
  208. });
  209. }
  210. debug!(target: "CLIENT", "End build inputs");
  211. Ok(inputs)
  212. }
  213. pub async fn connect_to_subscriber_from_cashier(
  214. &self,
  215. cashier_wallet: CashierDbPtr,
  216. notify: async_channel::Sender<(jubjub::SubgroupPoint, u64)>,
  217. ) -> Result<()> {
  218. // start subscribing
  219. debug!(target: "CLIENT", "Start subscriber for cashier");
  220. let gateway_slabs_sub: GatewaySlabsSubscriber = self.gateway.start_subscriber().await?;
  221. let secret_key = self.main_keypair.private;
  222. let state = self.state.clone();
  223. let task: smol::Task<Result<()>> = smol::spawn(async move {
  224. loop {
  225. let slab = gateway_slabs_sub.recv().await?;
  226. debug!(target: "CLIENT", "Received new slab");
  227. debug!(target: "CLIENT", "Starting build tx from slab");
  228. let tx = tx::Transaction::decode(&slab.get_payload()[..]);
  229. if let Err(e) = tx {
  230. warn!("TX: {}", e.to_string());
  231. continue;
  232. }
  233. let mut state = state.lock().await;
  234. let update = state_transition(&state, tx?);
  235. if let Err(e) = update {
  236. warn!("state transition: {}", e.to_string());
  237. continue;
  238. }
  239. let mut secret_keys: Vec<jubjub::Fr> = vec![secret_key];
  240. let mut withdraw_keys = cashier_wallet.get_withdraw_private_keys()?;
  241. secret_keys.append(&mut withdraw_keys);
  242. state
  243. .apply(update?, secret_keys.clone(), notify.clone())
  244. .await?;
  245. }
  246. });
  247. task.detach();
  248. debug!(target: "CLIENT", "End subscriber for cashier");
  249. Ok(())
  250. }
  251. pub async fn connect_to_subscriber(&self) -> Result<()> {
  252. // start subscribing
  253. debug!(target: "CLIENT", "Start subscriber");
  254. let gateway_slabs_sub: GatewaySlabsSubscriber = self.gateway.start_subscriber().await?;
  255. let (notify, _) = async_channel::unbounded::<(jubjub::SubgroupPoint, u64)>();
  256. let secret_key = self.main_keypair.private;
  257. let state = self.state.clone();
  258. let task: smol::Task<Result<()>> = smol::spawn(async move {
  259. loop {
  260. let slab = gateway_slabs_sub.recv().await?;
  261. debug!(target: "CLIENT", "Received new slab");
  262. debug!(target: "CLIENT", "Starting build tx from slab");
  263. let tx = tx::Transaction::decode(&slab.get_payload()[..]);
  264. if let Err(e) = tx {
  265. warn!("TX: {}", e.to_string());
  266. continue;
  267. }
  268. let mut state = state.lock().await;
  269. let update = state_transition(&state, tx?);
  270. if let Err(e) = update {
  271. warn!("state transition: {}", e.to_string());
  272. continue;
  273. }
  274. let secret_keys: Vec<jubjub::Fr> = vec![secret_key];
  275. state
  276. .apply(update?, secret_keys.clone(), notify.clone())
  277. .await?;
  278. }
  279. });
  280. task.detach();
  281. Ok(())
  282. }
  283. pub async fn init_db(&self) -> Result<()> {
  284. self.state.lock().await.wallet.init_db().await
  285. }
  286. pub async fn key_gen(&self) -> Result<()> {
  287. self.state.lock().await.wallet.key_gen()
  288. }
  289. //pub async fn token_and_balances(&self) -> Result<()> {
  290. // self.state.lock().await.wallet.get_token_ids()
  291. //}
  292. pub async fn token_id_exists(&self, token_id: &jubjub::Fr) -> Result<bool> {
  293. self.state.lock().await.wallet.token_id_exists(token_id)
  294. }
  295. pub async fn get_token_id(&self) -> Result<Vec<jubjub::Fr>> {
  296. self.state.lock().await.wallet.get_token_id()
  297. }
  298. }
  299. pub struct State {
  300. // The entire merkle tree state
  301. pub tree: CommitmentTree<MerkleNode>,
  302. // List of all previous and the current merkle roots
  303. // This is the hashed value of all the children.
  304. pub merkle_roots: RocksColumn<columns::MerkleRoots>,
  305. // Nullifiers prevent double spending
  306. pub nullifiers: RocksColumn<columns::Nullifiers>,
  307. // Mint verifying key used by ZK
  308. pub mint_pvk: groth16::PreparedVerifyingKey<Bls12>,
  309. // Spend verifying key used by ZK
  310. pub spend_pvk: groth16::PreparedVerifyingKey<Bls12>,
  311. pub wallet: WalletPtr,
  312. }
  313. impl ProgramState for State {
  314. fn is_valid_cashier_public_key(&self, public: &jubjub::SubgroupPoint) -> bool {
  315. debug!(target: "CLIENT STATE", "Check if it is valid cashier public key");
  316. if let Ok(pub_keys) = self.wallet.get_cashier_public_keys() {
  317. if pub_keys.is_empty() {
  318. error!(target: "State", "No cashier public key");
  319. return false;
  320. }
  321. return pub_keys.contains(public);
  322. }
  323. false
  324. }
  325. fn is_valid_merkle(&self, merkle_root: &MerkleNode) -> bool {
  326. debug!(target: "CLIENT STATE", "Check if it is valid merkle");
  327. if let Ok(mr) = self.merkle_roots.key_exist(*merkle_root) {
  328. return mr;
  329. }
  330. false
  331. }
  332. fn nullifier_exists(&self, nullifier: &Nullifier) -> bool {
  333. debug!(target: "CLIENT STATE", "Check if nullifier exists");
  334. if let Ok(nl) = self.nullifiers.key_exist(nullifier.repr) {
  335. return nl;
  336. }
  337. false
  338. }
  339. // load from disk
  340. fn mint_pvk(&self) -> &groth16::PreparedVerifyingKey<Bls12> {
  341. &self.mint_pvk
  342. }
  343. fn spend_pvk(&self) -> &groth16::PreparedVerifyingKey<Bls12> {
  344. &self.spend_pvk
  345. }
  346. }
  347. impl State {
  348. pub async fn apply(
  349. &mut self,
  350. update: StateUpdate,
  351. secret_keys: Vec<jubjub::Fr>,
  352. notify: async_channel::Sender<(jubjub::SubgroupPoint, u64)>,
  353. ) -> Result<()> {
  354. // Extend our list of nullifiers with the ones from the update
  355. debug!(target: "CLIENT STATE", "Extend nullifiers");
  356. for nullifier in update.nullifiers {
  357. self.nullifiers.put(nullifier, vec![] as Vec<u8>)?;
  358. }
  359. debug!(target: "CLIENT STATE", "Update merkle tree and witness ");
  360. // Update merkle tree and witnesses
  361. for (coin, enc_note) in update.coins.into_iter().zip(update.enc_notes.iter()) {
  362. // Add the new coins to the merkle tree
  363. let node = MerkleNode::from_coin(&coin);
  364. self.tree.append(node).expect("Append to merkle tree");
  365. debug!(target: "CLIENT STATE", "Keep track of all merkle roots");
  366. // Keep track of all merkle roots that have existed
  367. self.merkle_roots.put(self.tree.root(), vec![] as Vec<u8>)?;
  368. debug!(target: "CLIENT STATE", "Update witness");
  369. // Also update all the coin witnesses
  370. for (coin_id, witness) in self.wallet.get_witnesses()?.iter_mut() {
  371. witness.append(node).expect("Append to witness");
  372. self.wallet.update_witness(*coin_id, witness.clone())?;
  373. }
  374. debug!(target: "CLIENT STATE", "iterate over secret_keys to decrypt note");
  375. for secret in secret_keys.iter() {
  376. if let Some(note) = Self::try_decrypt_note(enc_note, *secret) {
  377. // We need to keep track of the witness for this coin.
  378. // This allows us to prove inclusion of the coin in the merkle tree with ZK.
  379. // Just as we update the merkle tree with every new coin, so we do the same with
  380. // the witness.
  381. // Derive the current witness from the current tree.
  382. // This is done right after we add our coin to the tree (but before any other
  383. // coins are added)
  384. // Make a new witness for this coin
  385. let witness = IncrementalWitness::from_tree(&self.tree);
  386. let own_coin = OwnCoin {
  387. coin: coin.clone(),
  388. note: note.clone(),
  389. secret: *secret,
  390. witness: witness.clone(),
  391. };
  392. self.wallet.put_own_coins(own_coin)?;
  393. let pub_key = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
  394. debug!(target: "CLIENT STATE", "Received a coin: amount {} ", note.value);
  395. debug!(target: "CLIENT STATE", "Send a notification");
  396. notify.send((pub_key, note.value)).await?;
  397. }
  398. }
  399. }
  400. Ok(())
  401. }
  402. fn try_decrypt_note(ciphertext: &EncryptedNote, secret: jubjub::Fr) -> Option<Note> {
  403. match ciphertext.decrypt(&secret) {
  404. // ... and return the decrypted note for this coin.
  405. Ok(note) => Some(note),
  406. // We weren't able to decrypt the note with our key.
  407. Err(_) => None,
  408. }
  409. }
  410. }
  411. impl std::error::Error for ClientFailed {}
  412. impl std::fmt::Display for ClientFailed {
  413. fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
  414. match self {
  415. ClientFailed::NotEnoughValue(i) => {
  416. write!(f, "There is no enough value {}", i)
  417. }
  418. ClientFailed::InvalidAddress(i) => {
  419. write!(f, "Invalid Address {}", i)
  420. }
  421. ClientFailed::InvalidAmount(i) => {
  422. write!(f, "Invalid Amount {}", i)
  423. }
  424. ClientFailed::UnableToGetDepositAddress => f.write_str("Unable to get deposit address"),
  425. ClientFailed::UnableToGetWithdrawAddress => {
  426. f.write_str("Unable to get withdraw address")
  427. }
  428. ClientFailed::DoesNotHaveCashierPublicKey => {
  429. f.write_str("Does not have cashier public key")
  430. }
  431. ClientFailed::DoesNotHaveKeypair => f.write_str("Does not have keypair"),
  432. ClientFailed::EmptyPassword => f.write_str("Password is empty. Cannot create database"),
  433. ClientFailed::WalletInitialized => f.write_str("Wallet already initalized"),
  434. ClientFailed::KeyExists => f.write_str("Keypair already exists"),
  435. ClientFailed::ClientError(i) => {
  436. write!(f, "ClientError: {}", i)
  437. }
  438. }
  439. }
  440. }
  441. impl From<super::error::Error> for ClientFailed {
  442. fn from(err: super::error::Error) -> ClientFailed {
  443. ClientFailed::ClientError(err.to_string())
  444. }
  445. }
  446. pub type ClientResult<T> = std::result::Result<T, ClientFailed>;