client.rs 17 KB

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