client.rs 18 KB

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