client.rs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. use async_std::sync::{Arc, Mutex};
  2. use incrementalmerkletree::Tree;
  3. use log::{debug, info, warn};
  4. use pasta_curves::pallas;
  5. use smol::Executor;
  6. use url::Url;
  7. use crate::{
  8. blockchain::{rocks::columns, Rocks, RocksColumn, Slab},
  9. crypto::{coin::Coin, merkle_node::MerkleNode, schnorr, util::mod_r_p},
  10. serial::{serialize, Decodable, Encodable},
  11. service::GatewayClient,
  12. state::{state_transition, State},
  13. tx,
  14. wallet::{CashierDbPtr, Keypair, WalletPtr},
  15. Result,
  16. };
  17. #[derive(Debug, Clone, thiserror::Error)]
  18. pub enum ClientFailed {
  19. #[error("Here is not enough value {0}")]
  20. NotEnoughValue(u64),
  21. #[error("Invalid Address {0}")]
  22. InvalidAddress(String),
  23. #[error("Invalid Amount {0}")]
  24. InvalidAmount(u64),
  25. #[error("Unable to get deposit address")]
  26. UnableToGetDepositAddress,
  27. #[error("Unable to get withdraw address")]
  28. UnableToGetWithdrawAddress,
  29. #[error("Does not have cashier public key")]
  30. DoesNotHaveCashierPublicKey,
  31. #[error("Does not have keypair")]
  32. DoesNotHaveKeypair,
  33. #[error("Password is empty. Cannot create database")]
  34. EmptyPassword,
  35. #[error("Wallet already initalized")]
  36. WalletInitialized,
  37. #[error("Keypair already exists")]
  38. KeyExists,
  39. #[error("{0}")]
  40. ClientError(String),
  41. #[error("Verify error: {0}")]
  42. VerifyError(String),
  43. }
  44. pub type ClientResult<T> = std::result::Result<T, ClientFailed>;
  45. impl From<super::error::Error> for ClientFailed {
  46. fn from(err: super::error::Error) -> ClientFailed {
  47. ClientFailed::ClientError(err.to_string())
  48. }
  49. }
  50. impl From<crate::state::VerifyFailed> for ClientFailed {
  51. fn from(err: crate::state::VerifyFailed) -> ClientFailed {
  52. ClientFailed::VerifyError(err.to_string())
  53. }
  54. }
  55. pub struct Client {
  56. pub main_keypair: Keypair,
  57. gateway: GatewayClient,
  58. wallet: WalletPtr,
  59. }
  60. impl Client {
  61. pub async fn new(
  62. rocks: Arc<Rocks>,
  63. gateway_addrs: (Url, Url),
  64. wallet: WalletPtr,
  65. ) -> Result<Self> {
  66. wallet.init_db().await?;
  67. // Generate a new keypair if we don't have any.
  68. if wallet.get_keypairs().await?.is_empty() {
  69. wallet.key_gen().await?;
  70. }
  71. // TODO: Think about multiple keypairs
  72. let main_keypair = wallet.get_keypairs().await?[0].clone();
  73. info!("Main keypair: {}", bs58::encode(&serialize(&main_keypair.public)).into_string());
  74. debug!("Creating GatewayClient");
  75. let slabstore = RocksColumn::<columns::Slabs>::new(rocks);
  76. let gateway = GatewayClient::new(gateway_addrs.0, gateway_addrs.1, slabstore)?;
  77. let client = Client { main_keypair, gateway, wallet };
  78. Ok(client)
  79. }
  80. pub async fn start(&mut self) -> Result<()> {
  81. self.gateway.start().await
  82. }
  83. async fn build_slab_from_tx(
  84. &mut self,
  85. pubkey: pallas::Point,
  86. value: u64,
  87. token_id: pallas::Base,
  88. clear_input: bool,
  89. state: Arc<Mutex<State>>,
  90. ) -> ClientResult<Vec<Coin>> {
  91. debug!("Start build slab from tx");
  92. let mut clear_inputs: Vec<tx::TransactionBuilderClearInputInfo> = vec![];
  93. let mut inputs: Vec<tx::TransactionBuilderInputInfo> = vec![];
  94. let mut outputs: Vec<tx::TransactionBuilderOutputInfo> = vec![];
  95. let mut coins: Vec<Coin> = vec![];
  96. if clear_input {
  97. // TODO: FIXME:
  98. let base_secret = self.main_keypair.private;
  99. let signature_secret = schnorr::SecretKey(mod_r_p(base_secret));
  100. let input = tx::TransactionBuilderClearInputInfo { value, token_id, signature_secret };
  101. clear_inputs.push(input);
  102. } else {
  103. debug!("Start build inputs");
  104. let mut inputs_value = 0_u64;
  105. let state_m = state.lock().await;
  106. let own_coins = self.wallet.get_own_coins().await?;
  107. for own_coin in own_coins.iter() {
  108. if inputs_value >= value {
  109. break
  110. }
  111. let node = MerkleNode(own_coin.coin.inner());
  112. let (leaf_position, merkle_path) = state_m.tree.authentication_path(&node).unwrap();
  113. // TODO: What is this counting? Is it everything or does it know to separate
  114. // different tokens?
  115. inputs_value += own_coin.note.value;
  116. let input = tx::TransactionBuilderInputInfo {
  117. leaf_position,
  118. merkle_path,
  119. secret: own_coin.secret,
  120. note: own_coin.note.clone(),
  121. };
  122. inputs.push(input);
  123. coins.push(own_coin.coin.clone());
  124. }
  125. if inputs_value < value {
  126. return Err(ClientFailed::NotEnoughValue(inputs_value))
  127. }
  128. if inputs_value > value {
  129. let return_value: u64 = inputs_value - value;
  130. outputs.push(tx::TransactionBuilderOutputInfo {
  131. value: return_value,
  132. token_id,
  133. public: self.main_keypair.public,
  134. });
  135. }
  136. debug!("End build inputs");
  137. }
  138. outputs.push(tx::TransactionBuilderOutputInfo { value, token_id, public: pubkey });
  139. let builder = tx::TransactionBuilder { clear_inputs, inputs, outputs };
  140. let tx: tx::Transaction;
  141. let mut tx_data = vec![];
  142. tx = builder.build()?;
  143. tx.encode(&mut tx_data).expect("encode tx");
  144. let slab = Slab::new(tx_data);
  145. debug!("End build slab from tx");
  146. // Check if it's valid before sending to gateway
  147. let state = &*state.lock().await;
  148. state_transition(state, tx)?;
  149. self.gateway.put_slab(slab).await?;
  150. Ok(coins)
  151. }
  152. pub async fn send(
  153. &mut self,
  154. pubkey: pallas::Point,
  155. amount: u64,
  156. token_id: pallas::Base,
  157. clear_input: bool,
  158. state: Arc<Mutex<State>>,
  159. ) -> ClientResult<()> {
  160. // TODO: TOKEN debug
  161. debug!("Start send {}", amount);
  162. if amount == 0 {
  163. return Err(ClientFailed::InvalidAmount(0))
  164. }
  165. let coins = self.build_slab_from_tx(pubkey, amount, token_id, clear_input, state).await?;
  166. for coin in coins.iter() {
  167. self.wallet.confirm_spend_coin(coin).await?;
  168. }
  169. debug!("End send {}", amount);
  170. Ok(())
  171. }
  172. async fn update_state(
  173. secret_keys: Vec<pallas::Base>,
  174. slab: &Slab,
  175. state: Arc<Mutex<State>>,
  176. wallet: WalletPtr,
  177. notify: Option<async_channel::Sender<(pallas::Point, u64)>>,
  178. ) -> Result<()> {
  179. debug!("Build tx from slab and update the state");
  180. let tx = tx::Transaction::decode(&slab.get_payload()[..])?;
  181. let st = &*state.lock().await;
  182. let update = state_transition(st, tx)?;
  183. let mut st = state.lock().await;
  184. st.apply(update, secret_keys, notify, wallet).await?;
  185. Ok(())
  186. }
  187. pub async fn connect_to_subscriber_from_cashier(
  188. &self,
  189. state: Arc<Mutex<State>>,
  190. cashier_wallet: CashierDbPtr,
  191. notify: async_channel::Sender<(pallas::Point, u64)>,
  192. executor: Arc<Executor<'_>>,
  193. ) -> Result<()> {
  194. debug!("Start subscriber for cashier");
  195. let gateway_slabs_sub = self.gateway.start_subscriber(executor.clone()).await?;
  196. let secret_key = self.main_keypair.private;
  197. let wallet = self.wallet.clone();
  198. //let task: smol::Task<Result<()>> = executor.spawn(async move {
  199. let task: smol::Task<Result<()>> = executor.spawn(async move {
  200. loop {
  201. let slab = gateway_slabs_sub.recv().await?;
  202. debug!("Received new slab");
  203. let mut secret_keys: Vec<pallas::Base> = vec![secret_key];
  204. let mut withdraw_keys = cashier_wallet.get_withdraw_private_keys().await?;
  205. secret_keys.append(&mut withdraw_keys);
  206. let update_state = Self::update_state(
  207. secret_keys,
  208. &slab,
  209. state.clone(),
  210. wallet.clone(),
  211. Some(notify.clone()),
  212. )
  213. .await;
  214. if let Err(e) = update_state {
  215. warn!("Update state: {}", e);
  216. continue
  217. }
  218. }
  219. });
  220. task.detach();
  221. Ok(())
  222. }
  223. }