rpc_token.rs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2023 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 anyhow::{anyhow, Result};
  19. use darkfi::{
  20. tx::Transaction,
  21. util::parse::decode_base10,
  22. zk::{proof::ProvingKey, vm::ZkCircuit, vm_heap::empty_witnesses},
  23. zkas::ZkBinary,
  24. };
  25. use darkfi_money_contract::{
  26. client::{token_freeze_v1::TokenFreezeCallBuilder, token_mint_v1::TokenMintCallBuilder},
  27. MoneyFunction, MONEY_CONTRACT_ZKAS_TOKEN_FRZ_NS_V1, MONEY_CONTRACT_ZKAS_TOKEN_MINT_NS_V1,
  28. };
  29. use darkfi_sdk::{
  30. crypto::{contract_id::MONEY_CONTRACT_ID, Keypair, PublicKey, TokenId},
  31. pasta::pallas,
  32. tx::ContractCall,
  33. };
  34. use darkfi_serial::Encodable;
  35. use rand::rngs::OsRng;
  36. use super::Drk;
  37. impl Drk {
  38. /// Create a token mint transaction. Returns the transaction object on success.
  39. pub async fn mint_token(
  40. &self,
  41. amount: &str,
  42. recipient: PublicKey,
  43. token_id: TokenId,
  44. ) -> Result<Transaction> {
  45. // TODO: Mint directly into DAO treasury
  46. let spend_hook = pallas::Base::zero();
  47. let user_data = pallas::Base::zero();
  48. let amount = decode_base10(amount, 8, false)?;
  49. let mut tokens = self.list_tokens().await?;
  50. tokens.retain(|x| x.0 == token_id);
  51. if tokens.is_empty() {
  52. return Err(anyhow!("Did not find mint authority for token ID {}", token_id))
  53. }
  54. assert!(tokens.len() == 1);
  55. let mint_authority = Keypair::new(tokens[0].1);
  56. if tokens[0].2 {
  57. return Err(anyhow!("This token mint is marked as frozen in the wallet"))
  58. }
  59. // Now we need to do a lookup for the zkas proof bincodes, and create
  60. // the circuit objects and proving keys so we can build the transaction.
  61. // We also do this through the RPC.
  62. let zkas_bins = self.lookup_zkas(&MONEY_CONTRACT_ID).await?;
  63. let zkas_ns = MONEY_CONTRACT_ZKAS_TOKEN_MINT_NS_V1;
  64. let Some(token_mint_zkbin) = zkas_bins.iter().find(|x| x.0 == zkas_ns) else {
  65. return Err(anyhow!("Token mint circuit not found"))
  66. };
  67. let token_mint_zkbin = ZkBinary::decode(&token_mint_zkbin.1)?;
  68. let token_mint_circuit =
  69. ZkCircuit::new(empty_witnesses(&token_mint_zkbin), &token_mint_zkbin);
  70. eprintln!("Creating token mint circuit proving keys");
  71. let token_mint_pk = ProvingKey::build(token_mint_zkbin.k, &token_mint_circuit);
  72. let mint_builder = TokenMintCallBuilder {
  73. mint_authority,
  74. recipient,
  75. amount,
  76. spend_hook,
  77. user_data,
  78. token_mint_zkbin,
  79. token_mint_pk,
  80. };
  81. eprintln!("Building transaction parameters");
  82. let debris = mint_builder.build()?;
  83. // Encode and sign the transaction
  84. let mut data = vec![MoneyFunction::TokenMintV1 as u8];
  85. debris.params.encode(&mut data)?;
  86. let calls = vec![ContractCall { contract_id: *MONEY_CONTRACT_ID, data }];
  87. let proofs = vec![debris.proofs];
  88. let mut tx = Transaction { calls, proofs, signatures: vec![] };
  89. let sigs = tx.create_sigs(&mut OsRng, &[mint_authority.secret])?;
  90. tx.signatures = vec![sigs];
  91. Ok(tx)
  92. }
  93. /// Create a token freeze transaction. Returns the transaction object on success.
  94. pub async fn freeze_token(&self, token_id: TokenId) -> Result<Transaction> {
  95. let mut tokens = self.list_tokens().await?;
  96. tokens.retain(|x| x.0 == token_id);
  97. if tokens.is_empty() {
  98. return Err(anyhow!("Did not find mint authority for token ID {}", token_id))
  99. }
  100. assert!(tokens.len() == 1);
  101. let mint_authority = Keypair::new(tokens[0].1);
  102. if tokens[0].2 {
  103. return Err(anyhow!("This token is already marked as frozen in the wallet"))
  104. }
  105. let zkas_bins = self.lookup_zkas(&MONEY_CONTRACT_ID).await?;
  106. let zkas_ns = MONEY_CONTRACT_ZKAS_TOKEN_FRZ_NS_V1;
  107. let Some(token_freeze_zkbin) = zkas_bins.iter().find(|x| x.0 == zkas_ns) else {
  108. return Err(anyhow!("Token freeze circuit not found"))
  109. };
  110. let token_freeze_zkbin = ZkBinary::decode(&token_freeze_zkbin.1)?;
  111. let token_freeze_circuit =
  112. ZkCircuit::new(empty_witnesses(&token_freeze_zkbin), &token_freeze_zkbin);
  113. eprintln!("Creating token freeze circuit proving keys");
  114. let token_freeze_pk = ProvingKey::build(token_freeze_zkbin.k, &token_freeze_circuit);
  115. let freeze_builder =
  116. TokenFreezeCallBuilder { mint_authority, token_freeze_zkbin, token_freeze_pk };
  117. eprintln!("Building transaction parameters");
  118. let debris = freeze_builder.build()?;
  119. // Encode and sign the transaction
  120. let mut data = vec![MoneyFunction::TokenFreezeV1 as u8];
  121. debris.params.encode(&mut data)?;
  122. let calls = vec![ContractCall { contract_id: *MONEY_CONTRACT_ID, data }];
  123. let proofs = vec![debris.proofs];
  124. let mut tx = Transaction { calls, proofs, signatures: vec![] };
  125. let sigs = tx.create_sigs(&mut OsRng, &[mint_authority.secret])?;
  126. tx.signatures = vec![sigs];
  127. Ok(tx)
  128. }
  129. }