client.rs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2022 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use async_std::sync::{Arc, Mutex};
  19. use darkfi_sdk::crypto::{constants::MERKLE_DEPTH, MerkleNode};
  20. use incrementalmerkletree::{bridgetree::BridgeTree, Tree};
  21. use lazy_init::Lazy;
  22. use log::{debug, error, info};
  23. use pasta_curves::group::ff::PrimeField;
  24. use super::state::{state_transition, State};
  25. use crate::{
  26. crypto::{
  27. address::Address,
  28. coin::{Coin, OwnCoin},
  29. keypair::{Keypair, PublicKey},
  30. proof::ProvingKey,
  31. types::DrkTokenId,
  32. },
  33. tx::{
  34. builder::{
  35. TransactionBuilder, TransactionBuilderClearInputInfo, TransactionBuilderInputInfo,
  36. TransactionBuilderOutputInfo,
  37. },
  38. Transaction,
  39. },
  40. wallet::walletdb::{Balance, Balances, WalletPtr},
  41. zk::circuit::{BurnContract, MintContract},
  42. ClientFailed, ClientResult, Result,
  43. };
  44. /// The Client structure, used for transaction operations.
  45. /// This includes, receiving, broadcasting, and building.
  46. pub struct Client {
  47. pub main_keypair: Mutex<Keypair>,
  48. pub wallet: WalletPtr,
  49. mint_pk: Lazy<ProvingKey>,
  50. burn_pk: Lazy<ProvingKey>,
  51. }
  52. impl Client {
  53. pub async fn new(wallet: WalletPtr) -> Result<Self> {
  54. // Initialize or load the wallet
  55. wallet.init_db().await?;
  56. // Get default keypair or create one
  57. let main_keypair = wallet.get_default_keypair_or_create_one().await?;
  58. info!(target: "client", "Main keypair: {}", Address::from(main_keypair.public));
  59. // Generate merkle tree if we don't have one.
  60. // TODO: See what to do about this
  61. if wallet.get_tree().await.is_err() {
  62. wallet.tree_gen().await?;
  63. }
  64. Ok(Self {
  65. main_keypair: Mutex::new(main_keypair),
  66. wallet,
  67. mint_pk: Lazy::new(),
  68. burn_pk: Lazy::new(),
  69. })
  70. }
  71. // TODO: Better function name
  72. async fn build_slab_from_tx(
  73. &self,
  74. pubkey: PublicKey,
  75. value: u64,
  76. token_id: DrkTokenId,
  77. clear_input: bool,
  78. state: Arc<Mutex<State>>,
  79. ) -> ClientResult<(Transaction, Vec<Coin>)> {
  80. debug!("build_slab_from_tx(): Begin building slab from tx");
  81. let mut clear_inputs = vec![];
  82. let mut inputs = vec![];
  83. let mut outputs = vec![];
  84. let mut coins = vec![];
  85. if clear_input {
  86. debug!("build_slab_from_tx(): Building clear input");
  87. let signature_secret = self.main_keypair.lock().await.secret;
  88. let input = TransactionBuilderClearInputInfo { value, token_id, signature_secret };
  89. clear_inputs.push(input);
  90. } else {
  91. debug!("build_slab_from_tx(): Building tx inputs");
  92. let mut inputs_value = 0;
  93. let state_m = state.lock().await;
  94. let own_coins = self.wallet.get_own_coins().await?;
  95. for own_coin in own_coins.iter() {
  96. if inputs_value >= value {
  97. debug!("build_slab_from_tx(): inputs_value >= value");
  98. break
  99. }
  100. let leaf_position = own_coin.leaf_position;
  101. let root = state_m.tree.root(0).unwrap();
  102. let merkle_path = state_m.tree.authentication_path(leaf_position, &root).unwrap();
  103. inputs_value += own_coin.note.value;
  104. let input = TransactionBuilderInputInfo {
  105. leaf_position,
  106. merkle_path,
  107. secret: own_coin.secret,
  108. note: own_coin.note.clone(),
  109. };
  110. inputs.push(input);
  111. coins.push(own_coin.coin);
  112. }
  113. // Release state lock
  114. drop(state_m);
  115. if inputs_value < value {
  116. error!("build_slab_from_tx(): Not enough value to build tx inputs");
  117. return Err(ClientFailed::NotEnoughValue(inputs_value))
  118. }
  119. if inputs_value > value {
  120. let return_value = inputs_value - value;
  121. outputs.push(TransactionBuilderOutputInfo {
  122. value: return_value,
  123. token_id,
  124. public: self.main_keypair.lock().await.public,
  125. });
  126. }
  127. debug!("build_slab_from_tx(): Finished building inputs");
  128. }
  129. outputs.push(TransactionBuilderOutputInfo { value, token_id, public: pubkey });
  130. let builder = TransactionBuilder { clear_inputs, inputs, outputs };
  131. let mint_pk = self.mint_pk.get_or_create(Client::build_mint_pk);
  132. let burn_pk = self.burn_pk.get_or_create(Client::build_burn_pk);
  133. let tx = builder.build(mint_pk, burn_pk)?;
  134. // Check if state transition is valid before broadcasting
  135. debug!("build_slab_from_tx(): Checking if state transition is valid");
  136. let state = &*state.lock().await;
  137. debug!("build_slab_from_tx(): Got state lock");
  138. state_transition(state, tx.clone())?;
  139. debug!("build_slab_from_tx(): Successful state transition");
  140. Ok((tx, coins))
  141. }
  142. /// Build a transaction given the required parameters and state machine.
  143. pub async fn build_transaction(
  144. &self,
  145. pubkey: PublicKey,
  146. amount: u64,
  147. token_id: DrkTokenId,
  148. clear_input: bool,
  149. state: Arc<Mutex<State>>,
  150. ) -> ClientResult<Transaction> {
  151. debug!(
  152. "send(): Sending {} {} tokens",
  153. amount,
  154. bs58::encode(token_id.to_repr()).into_string()
  155. );
  156. if amount == 0 {
  157. return Err(ClientFailed::InvalidAmount(0))
  158. }
  159. if !self.wallet.token_id_exists(token_id).await? && !clear_input {
  160. return Err(ClientFailed::NotEnoughValue(amount))
  161. }
  162. let (tx, coins) =
  163. self.build_slab_from_tx(pubkey, amount, token_id, clear_input, state).await?;
  164. for coin in coins.iter() {
  165. // TODO: This should be more robust. In case our transaction is denied,
  166. // we want to revert to be able to send again.
  167. self.wallet.confirm_spend_coin(coin).await?;
  168. }
  169. debug!("send(): Sent {}", amount);
  170. Ok(tx)
  171. }
  172. pub async fn init_db(&self) -> Result<()> {
  173. self.wallet.init_db().await
  174. }
  175. pub async fn get_own_coins(&self) -> Result<Vec<OwnCoin>> {
  176. self.wallet.get_own_coins().await
  177. }
  178. pub async fn confirm_spend_coin(&self, coin: &Coin) -> Result<()> {
  179. self.wallet.confirm_spend_coin(coin).await
  180. }
  181. pub async fn revert_spend_coin(&self, coin: &Coin) -> Result<()> {
  182. self.wallet.revert_spend_coin(coin).await
  183. }
  184. pub async fn get_keypairs(&self) -> Result<Vec<Keypair>> {
  185. self.wallet.get_keypairs().await
  186. }
  187. pub async fn put_keypair(&self, keypair: &Keypair) -> Result<()> {
  188. self.wallet.put_keypair(keypair).await
  189. }
  190. pub async fn set_default_keypair(&self, public: &PublicKey) -> Result<()> {
  191. let kp = self.wallet.set_default_keypair(public).await?;
  192. let mut mk = self.main_keypair.lock().await;
  193. *mk = kp;
  194. drop(mk);
  195. Ok(())
  196. }
  197. pub async fn keygen(&self) -> Result<Address> {
  198. let kp = self.wallet.keygen().await?;
  199. Ok(Address::from(kp.public))
  200. }
  201. pub async fn get_balance(&self, token_id: DrkTokenId) -> Result<Option<Balance>> {
  202. self.wallet.get_balance(token_id).await
  203. }
  204. pub async fn get_balances(&self) -> Result<Balances> {
  205. self.wallet.get_balances().await
  206. }
  207. pub async fn get_coins_valtok(
  208. &self,
  209. value: u64,
  210. token_id: DrkTokenId,
  211. unspent: bool,
  212. ) -> Result<Vec<OwnCoin>> {
  213. self.wallet.get_coins_valtok(value, token_id, unspent).await
  214. }
  215. pub async fn get_tree(&self) -> Result<BridgeTree<MerkleNode, MERKLE_DEPTH>> {
  216. self.wallet.get_tree().await
  217. }
  218. fn build_mint_pk() -> ProvingKey {
  219. debug!("Building proving key for MintContract");
  220. ProvingKey::build(11, &MintContract::default())
  221. }
  222. fn build_burn_pk() -> ProvingKey {
  223. debug!("Building proving key for BurnContract");
  224. ProvingKey::build(11, &BurnContract::default())
  225. }
  226. }