client.rs 18 KB

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