parazyd 3 лет назад
Родитель
Сommit
a9a9146b7c

+ 45 - 8
bin/drk/src/main.rs

@@ -27,9 +27,8 @@ use anyhow::{anyhow, Context, Result};
 use clap::{CommandFactory, Parser, Subcommand};
 use clap_complete::{generate, Shell};
 use darkfi::{tx::Transaction, util::parse::decode_base10, zk::halo2::Field};
-use darkfi_money_contract::client::Coin;
 use darkfi_sdk::{
-    crypto::{PublicKey, SecretKey, TokenId},
+    crypto::{Coin, PublicKey, SecretKey, TokenId},
     pasta::{group::ff::PrimeField, pallas},
 };
 use darkfi_serial::{deserialize, serialize};
@@ -151,9 +150,6 @@ enum Subcmd {
         /// Amount to request from the faucet
         amount: String,
 
-        /// Token ID to request from the faucet
-        token: String,
-
         /// Optional address to send tokens to (defaults to main address in wallet)
         address: Option<String>,
     },
@@ -221,6 +217,10 @@ enum Subcmd {
     /// Manage Token aliases
     #[command(subcommand)]
     Alias(AliasSubcmd),
+
+    /// Token functionalities
+    #[command(subcommand)]
+    Token(TokenSubcmd),
 }
 
 #[derive(Subcommand)]
@@ -384,6 +384,36 @@ enum AliasSubcmd {
     },
 }
 
+#[derive(Subcommand)]
+enum TokenSubcmd {
+    /// Import a mint authority secret from stdin
+    Import,
+
+    /// Generate a new mint authority
+    GenerateMint,
+
+    /// List token IDs with available mint authorities
+    List,
+
+    /// Mint tokens
+    Mint {
+        /// Token ID to mint
+        token: String,
+
+        /// Amount to mint
+        amount: String,
+
+        /// Recipient of the minted tokens
+        recipient: String,
+    },
+
+    /// Freeze a token mint
+    Freeze {
+        /// Token ID mint to freeze
+        token: String,
+    },
+}
+
 pub struct Drk {
     pub rpc_client: RpcClient,
 }
@@ -649,10 +679,9 @@ async fn main() -> Result<()> {
             Ok(())
         }
 
-        Subcmd::Airdrop { faucet_endpoint, amount, token, address } => {
+        Subcmd::Airdrop { faucet_endpoint, amount, address } => {
             let amount = f64::from_str(&amount).with_context(|| "Invalid amount")?;
             let drk = Drk::new(args.endpoint).await?;
-            let token_id = drk.get_token(token).await.with_context(|| "Invalid Token ID")?;
 
             let address = match address {
                 Some(v) => PublicKey::from_str(v.as_str()).with_context(|| "Invalid address")?,
@@ -662,7 +691,7 @@ async fn main() -> Result<()> {
             };
 
             let txid = drk
-                .request_airdrop(faucet_endpoint, amount, token_id, address)
+                .request_airdrop(faucet_endpoint, amount, address)
                 .await
                 .with_context(|| "Failed to request airdrop")?;
 
@@ -1103,5 +1132,13 @@ async fn main() -> Result<()> {
                 Ok(())
             }
         },
+
+        Subcmd::Token(cmd) => match cmd {
+            TokenSubcmd::Import => todo!(),
+            TokenSubcmd::GenerateMint => todo!(),
+            TokenSubcmd::List => todo!(),
+            TokenSubcmd::Mint { token, amount, recipient } => todo!(),
+            TokenSubcmd::Freeze { token } => todo!(),
+        },
     }
 }

+ 2 - 3
bin/drk/src/rpc_airdrop.rs

@@ -18,7 +18,7 @@
 
 use anyhow::Result;
 use darkfi::rpc::{client::RpcClient, jsonrpc::JsonRequest};
-use darkfi_sdk::crypto::{PublicKey, TokenId};
+use darkfi_sdk::crypto::PublicKey;
 use serde_json::json;
 use url::Url;
 
@@ -31,11 +31,10 @@ impl Drk {
         &self,
         faucet_endpoint: Url,
         amount: f64,
-        token_id: TokenId,
         address: PublicKey,
     ) -> Result<String> {
         let rpc_client = RpcClient::new(faucet_endpoint).await?;
-        let params = json!([format!("{}", address), amount, format!("{}", token_id),]);
+        let params = json!([format!("{}", address), amount]);
         let req = JsonRequest::new("airdrop", params);
         let rep = rpc_client.oneshot_request(req).await?;
 

+ 1 - 1
bin/drk/src/rpc_dao.rs

@@ -495,7 +495,7 @@ impl Drk {
         let (xfer_params, xfer_proofs) =
             xfer_call.make(&mint_zkbin, &mint_pk, &burn_zkbin, &burn_pk)?;
 
-        let mut data = vec![MoneyFunction::Transfer as u8];
+        let mut data = vec![MoneyFunction::TransferV1 as u8];
         xfer_params.encode(&mut data)?;
         let xfer_call = ContractCall { contract_id: *MONEY_CONTRACT_ID, data };
 

+ 15 - 19
bin/drk/src/rpc_swap.rs

@@ -24,15 +24,16 @@ use darkfi::{
     zkas::ZkBinary,
 };
 use darkfi_money_contract::{
-    client::{build_half_swap_tx, EncryptedNote, Note},
-    model::MoneyTransferParams,
+    client::{build_half_swap_tx, MoneyNote},
+    model::MoneyTransferParamsV1,
     MoneyFunction, MONEY_CONTRACT_ZKAS_BURN_NS_V1, MONEY_CONTRACT_ZKAS_MINT_NS_V1,
 };
 use darkfi_sdk::{
     crypto::{
         contract_id::MONEY_CONTRACT_ID,
+        note::AeadEncryptedNote,
         pedersen::{pedersen_commitment_base, pedersen_commitment_u64, ValueBlind},
-        poseidon_hash, PublicKey, SecretKey, TokenId,
+        poseidon_hash, Coin, PublicKey, SecretKey, TokenId,
     },
     pasta::pallas,
     tx::ContractCall,
@@ -46,7 +47,7 @@ use super::Drk;
 /// Half of the swap data, includes the coin that is supposed to be sent,
 /// and the coin that is supposed to be received.
 pub struct PartialSwapData {
-    params: MoneyTransferParams,
+    params: MoneyTransferParamsV1,
     proofs: Vec<Proof>,
     value_pair: (u64, u64),
     token_pair: (TokenId, TokenId),
@@ -223,7 +224,7 @@ impl Drk {
                 &burn_pk,
             )?;
 
-        let full_params = MoneyTransferParams {
+        let full_params = MoneyTransferParamsV1 {
             clear_inputs: vec![],
             inputs: vec![partial.params.inputs[0].clone(), half_params.inputs[0].clone()],
             outputs: vec![partial.params.outputs[0].clone(), half_params.outputs[0].clone()],
@@ -236,7 +237,7 @@ impl Drk {
             half_proofs[1].clone(),
         ];
 
-        let mut data = vec![MoneyFunction::OtcSwap as u8];
+        let mut data = vec![MoneyFunction::OtcSwapV1 as u8];
         full_params.encode(&mut data)?;
         let mut tx = Transaction {
             calls: vec![ContractCall { contract_id, data }],
@@ -278,7 +279,7 @@ impl Drk {
                 return Err(anyhow!("Inspection failed"))
             }
 
-            let params: MoneyTransferParams = deserialize(&tx.calls[0].data[1..])?;
+            let params: MoneyTransferParamsV1 = deserialize(&tx.calls[0].data[1..])?;
             eprintln!("Parameters:\n{:#?}", params);
 
             if params.inputs.len() != 2 {
@@ -294,17 +295,14 @@ impl Drk {
             // Try to decrypt one of the outputs.
             let secret_keys = self.get_money_secrets().await?;
             let mut skey: Option<SecretKey> = None;
-            let mut note: Option<Note> = None;
+            let mut note: Option<MoneyNote> = None;
             let mut output_idx = 0;
 
             for output in &params.outputs {
-                let ciphertext = output.ciphertext.clone();
-                let ephem_public = output.ephem_public;
-                let e_note = EncryptedNote { ciphertext, ephem_public };
                 eprintln!("Trying to decrypt note in output {}", output_idx);
 
                 for secret in &secret_keys {
-                    if let Ok(d_note) = e_note.decrypt(secret) {
+                    if let Ok(d_note) = output.note.decrypt::<MoneyNote>(secret) {
                         let s: SecretKey = deserialize(&d_note.memo)?;
                         skey = Some(s);
                         note = Some(d_note);
@@ -335,14 +333,14 @@ impl Drk {
 
             let skey = skey.unwrap();
             let (pub_x, pub_y) = PublicKey::from_secret(skey).xy();
-            let coin = poseidon_hash([
+            let coin = Coin::from(poseidon_hash([
                 pub_x,
                 pub_y,
                 pallas::Base::from(note.value),
                 note.token_id.inner(),
                 note.serial,
                 note.coin_blind,
-            ]);
+            ]));
 
             if coin == params.outputs[output_idx].coin {
                 eprintln!("Output[{}] coin matches decrypted note metadata", output_idx);
@@ -409,18 +407,16 @@ impl Drk {
     pub async fn sign_swap(&self, tx: &mut Transaction) -> Result<()> {
         // We need our secret keys to try and decrypt the note
         let secret_keys = self.get_money_secrets().await?;
-        let params: MoneyTransferParams = deserialize(&tx.calls[0].data[1..])?;
+        let params: MoneyTransferParamsV1 = deserialize(&tx.calls[0].data[1..])?;
 
         // Our output should be outputs[0] so we try to decrypt that.
-        let ciphertext = params.outputs[0].ciphertext.clone();
-        let ephem_public = params.outputs[0].ephem_public;
-        let encrypted_note = EncryptedNote { ciphertext, ephem_public };
+        let encrypted_note = &params.outputs[0].note;
 
         eprintln!("Trying to decrypt note in outputs[0]");
         let mut skey = None;
 
         for secret in &secret_keys {
-            if let Ok(note) = encrypted_note.decrypt(secret) {
+            if let Ok(note) = encrypted_note.decrypt::<MoneyNote>(secret) {
                 let s: SecretKey = deserialize(&note.memo)?;
                 eprintln!("Successfully decrypted and found an ephemeral secret");
                 skey = Some(s);

+ 28 - 24
bin/drk/src/rpc_transfer.rs

@@ -25,7 +25,7 @@ use darkfi::{
 };
 use darkfi_dao_contract::dao_model::DaoBulla;
 use darkfi_money_contract::{
-    client::{build_transfer_tx, OwnCoin},
+    client::{transfer_v1::TransferCallBuilder, OwnCoin},
     MoneyFunction, MONEY_CONTRACT_ZKAS_BURN_NS_V1, MONEY_CONTRACT_ZKAS_MINT_NS_V1,
 };
 use darkfi_sdk::{
@@ -123,40 +123,44 @@ impl Drk {
         let mint_circuit = ZkCircuit::new(empty_witnesses(&mint_zkbin), mint_zkbin.clone());
         let burn_circuit = ZkCircuit::new(empty_witnesses(&burn_zkbin), burn_zkbin.clone());
 
-        eprintln!("Creating Mint circuit proving key");
+        eprintln!("Creating Mint and Burn circuit proving keys");
         let mint_pk = ProvingKey::build(k, &mint_circuit);
-        eprintln!("Creating Burn circuit proving key");
         let burn_pk = ProvingKey::build(k, &burn_circuit);
 
-        // Now we should have everything we need to build the transaction
-        let (params, proofs, secrets, spent_coins) = build_transfer_tx(
-            &keypair,
-            &recipient,
-            amount,
+        let transfer_builder = TransferCallBuilder {
+            keypair,
+            recipient,
+            value: amount,
             token_id,
-            spend_hook,
-            user_data,
-            user_data_blind,
-            &owncoins,
-            &tree,
-            &mint_zkbin,
-            &mint_pk,
-            &burn_zkbin,
-            &burn_pk,
-            false,
-        )?;
+            rcpt_spend_hook: spend_hook,
+            rcpt_user_data: user_data,
+            rcpt_user_data_blind: user_data_blind,
+            change_spend_hook: pallas::Base::zero(),
+            change_user_data: pallas::Base::zero(),
+            change_user_data_blind: user_data_blind, // FIXME: I'm reusing this blind but dunno why
+            coins: owncoins,
+            tree,
+            mint_zkbin,
+            mint_pk: ProvingKey::build(k, &mint_circuit),
+            burn_zkbin,
+            burn_pk: ProvingKey::build(k, &burn_circuit),
+            clear_input: false,
+        };
+
+        eprintln!("Building transaction parameters");
+        let debris = transfer_builder.build()?;
 
         // Encode and sign the transaction
-        let mut data = vec![MoneyFunction::Transfer as u8];
-        params.encode(&mut data)?;
+        let mut data = vec![MoneyFunction::TransferV1 as u8];
+        debris.params.encode(&mut data)?;
         let calls = vec![ContractCall { contract_id, data }];
-        let proofs = vec![proofs];
+        let proofs = vec![debris.proofs];
         let mut tx = Transaction { calls, proofs, signatures: vec![] };
-        let sigs = tx.create_sigs(&mut OsRng, &secrets)?;
+        let sigs = tx.create_sigs(&mut OsRng, &debris.signature_secrets)?;
         tx.signatures = vec![sigs];
 
         // We need to mark the coins we've spent in our wallet
-        for spent_coin in spent_coins {
+        for spent_coin in debris.spent_coins {
             self.mark_spent_coin(&spent_coin.coin).await?;
         }
 

+ 11 - 14
bin/drk/src/wallet_money.rs

@@ -21,7 +21,7 @@ use anyhow::{anyhow, Result};
 use darkfi::{rpc::jsonrpc::JsonRequest, tx::Transaction, wallet::walletdb::QueryType};
 use darkfi_money_contract::{
     client::{
-        Coin, EncryptedNote, Note, OwnCoin, MONEY_ALIASES_COL_ALIAS, MONEY_ALIASES_COL_TOKEN_ID,
+        MoneyNote, OwnCoin, MONEY_ALIASES_COL_ALIAS, MONEY_ALIASES_COL_TOKEN_ID,
         MONEY_ALIASES_TABLE, MONEY_COINS_COL_COIN, MONEY_COINS_COL_COIN_BLIND,
         MONEY_COINS_COL_IS_SPENT, MONEY_COINS_COL_LEAF_POSITION, MONEY_COINS_COL_MEMO,
         MONEY_COINS_COL_NULLIFIER, MONEY_COINS_COL_SECRET, MONEY_COINS_COL_SERIAL,
@@ -31,13 +31,13 @@ use darkfi_money_contract::{
         MONEY_KEYS_COL_IS_DEFAULT, MONEY_KEYS_COL_KEY_ID, MONEY_KEYS_COL_PUBLIC,
         MONEY_KEYS_COL_SECRET, MONEY_KEYS_TABLE, MONEY_TREE_COL_TREE, MONEY_TREE_TABLE,
     },
-    model::{MoneyTransferParams, Output},
+    model::{MoneyTransferParamsV1, Output},
     MoneyFunction,
 };
 use darkfi_sdk::{
     crypto::{
-        poseidon_hash, Keypair, MerkleNode, MerkleTree, Nullifier, PublicKey, SecretKey, TokenId,
-        MONEY_CONTRACT_ID,
+        poseidon_hash, Coin, Keypair, MerkleNode, MerkleTree, Nullifier, PublicKey, SecretKey,
+        TokenId, MONEY_CONTRACT_ID,
     },
     incrementalmerkletree,
     incrementalmerkletree::Tree,
@@ -334,7 +334,7 @@ impl Drk {
 
             let memo: Vec<u8> = serde_json::from_value(row[13].clone())?;
 
-            let note = Note {
+            let note = MoneyNote {
                 serial,
                 value,
                 token_id,
@@ -488,9 +488,9 @@ impl Drk {
         let mut outputs: Vec<Output> = vec![];
 
         for (i, call) in tx.calls.iter().enumerate() {
-            if call.contract_id == cid && call.data[0] == MoneyFunction::Transfer as u8 {
+            if call.contract_id == cid && call.data[0] == MoneyFunction::TransferV1 as u8 {
                 eprintln!("Found Money::Transfer in call {}", i);
-                let params: MoneyTransferParams = deserialize(&call.data[1..])?;
+                let params: MoneyTransferParamsV1 = deserialize(&call.data[1..])?;
 
                 for input in params.inputs {
                     nullifiers.push(input.nullifier);
@@ -503,9 +503,9 @@ impl Drk {
                 continue
             }
 
-            if call.contract_id == cid && call.data[0] == MoneyFunction::OtcSwap as u8 {
+            if call.contract_id == cid && call.data[0] == MoneyFunction::OtcSwapV1 as u8 {
                 eprintln!("Found Money::OtcSwap in call {}", i);
-                let params: MoneyTransferParams = deserialize(&call.data[1..])?;
+                let params: MoneyTransferParamsV1 = deserialize(&call.data[1..])?;
 
                 for input in params.inputs {
                     nullifiers.push(input.nullifier);
@@ -529,14 +529,11 @@ impl Drk {
             let coin = output.coin;
 
             // Append the new coin to the Merkle tree. Every coin has to be added.
-            tree.append(&MerkleNode::from(coin));
+            tree.append(&MerkleNode::from(coin.inner()));
 
             // Attempt to decrypt the note
-            let enc_note =
-                EncryptedNote { ciphertext: output.ciphertext, ephem_public: output.ephem_public };
-
             for secret in secrets.iter().chain(dao_secrets.iter()) {
-                if let Ok(note) = enc_note.decrypt(secret) {
+                if let Ok(note) = output.note.decrypt::<MoneyNote>(secret) {
                     eprintln!("Successfully decrypted a Money Note");
                     eprintln!("Witnessing coin in Merkle tree");
                     let leaf_position = tree.witness().unwrap();