client.rs 18 KB

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