client.rs 17 KB

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