Explorar o código

drk: fixed token freezing and added its fee call

skoupidi %!s(int64=2) %!d(string=hai) anos
pai
achega
c37618f354

+ 10 - 11
bin/drk/src/main.rs

@@ -1659,7 +1659,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
             TokenSubcmd::Freeze { token } => {
             TokenSubcmd::Freeze { token } => {
                 let drk =
                 let drk =
                     Drk::new(args.wallet_path, args.wallet_pass, Some(args.endpoint), ex).await?;
                     Drk::new(args.wallet_path, args.wallet_pass, Some(args.endpoint), ex).await?;
-                let _token_id = match drk.get_token(token).await {
+                let token_id = match drk.get_token(token).await {
                     Ok(t) => t,
                     Ok(t) => t,
                     Err(e) => {
                     Err(e) => {
                         eprintln!("Invalid Token ID: {e:?}");
                         eprintln!("Invalid Token ID: {e:?}");
@@ -1667,18 +1667,17 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                     }
                     }
                 };
                 };
 
 
-                panic!("temporarily disabled due to change of API for drk.mint_token() fn");
-                //let tx = match drk.freeze_token(token_id).await {
-                //    Ok(tx) => tx,
-                //    Err(e) => {
-                //        eprintln!("Failed to create token freeze transaction: {e:?}");
-                //        exit(2);
-                //    }
-                //};
+                let tx = match drk.freeze_token(token_id).await {
+                    Ok(tx) => tx,
+                    Err(e) => {
+                        eprintln!("Failed to create token freeze transaction: {e:?}");
+                        exit(2);
+                    }
+                };
 
 
-                //println!("{}", base64::encode(&serialize_async(&tx).await));
+                println!("{}", base64::encode(&serialize_async(&tx).await));
 
 
-                //Ok(())
+                Ok(())
             }
             }
         },
         },
 
 

+ 1 - 2
bin/drk/src/money.rs

@@ -754,8 +754,7 @@ impl Drk {
             MoneyFunction::AuthTokenFreezeV1 => {
             MoneyFunction::AuthTokenFreezeV1 => {
                 println!("[parse_money_call] Found Money::AuthTokenFreezeV1 call");
                 println!("[parse_money_call] Found Money::AuthTokenFreezeV1 call");
                 let params: MoneyAuthTokenFreezeParamsV1 = deserialize_async(&data[1..]).await?;
                 let params: MoneyAuthTokenFreezeParamsV1 = deserialize_async(&data[1..]).await?;
-                let token_id = TokenId::derive_public(params.mint_public);
-                freezes.push(token_id);
+                freezes.push(params.token_id);
             }
             }
             MoneyFunction::TokenMintV1 => {
             MoneyFunction::TokenMintV1 => {
                 println!("[parse_money_call] Found Money::TokenMintV1 call");
                 println!("[parse_money_call] Found Money::TokenMintV1 call");

+ 58 - 34
bin/drk/src/token.rs

@@ -213,10 +213,15 @@ impl Drk {
         // Decode provided amount
         // Decode provided amount
         let amount = decode_base10(amount, BALANCE_BASE10_DECIMALS, false)?;
         let amount = decode_base10(amount, BALANCE_BASE10_DECIMALS, false)?;
 
 
-        // Grab token ID mint authority
+        // Grab token ID mint authority and attribtes
         let token_mint_authority = self.get_token_mint_authority(&token_id).await?;
         let token_mint_authority = self.get_token_mint_authority(&token_id).await?;
+        let token_attrs =
+            self.derive_token_attributes(token_mint_authority.1, token_mint_authority.2);
         let mint_authority = Keypair::new(token_mint_authority.1);
         let mint_authority = Keypair::new(token_mint_authority.1);
 
 
+        // Sanity check
+        assert_eq!(token_id, token_attrs.to_token_id());
+
         // Now we need to do a lookup for the zkas proof bincodes, and create
         // Now we need to do a lookup for the zkas proof bincodes, and create
         // the circuit objects and proving keys so we can build the transaction.
         // the circuit objects and proving keys so we can build the transaction.
         // We also do this through the RPC.
         // We also do this through the RPC.
@@ -253,24 +258,6 @@ impl Drk {
         let auth_mint_pk = ProvingKey::build(auth_mint_zkbin.k, &auth_mint_circuit);
         let auth_mint_pk = ProvingKey::build(auth_mint_zkbin.k, &auth_mint_circuit);
         let fee_pk = ProvingKey::build(fee_zkbin.k, &fee_circuit);
         let fee_pk = ProvingKey::build(fee_zkbin.k, &fee_circuit);
 
 
-        // Create the Auth FuncID
-        let auth_func_id = FuncRef {
-            contract_id: *MONEY_CONTRACT_ID,
-            func_code: MoneyFunction::AuthTokenMintV1 as u8,
-        }
-        .to_func_id();
-
-        let (mint_auth_x, mint_auth_y) = mint_authority.public.xy();
-
-        let token_attrs = TokenAttributes {
-            auth_parent: auth_func_id,
-            user_data: poseidon_hash([mint_auth_x, mint_auth_y]),
-            blind: token_mint_authority.2,
-        };
-
-        // Sanity check
-        assert_eq!(token_id, token_attrs.to_token_id());
-
         // Build the coin attributes
         // Build the coin attributes
         let coin_attrs = CoinAttributes {
         let coin_attrs = CoinAttributes {
             public_key: recipient,
             public_key: recipient,
@@ -341,12 +328,19 @@ impl Drk {
     }
     }
 
 
     /// Create a token freeze transaction. Returns the transaction object on success.
     /// Create a token freeze transaction. Returns the transaction object on success.
-    pub async fn freeze_token(&self, token_attrs: TokenAttributes) -> Result<Transaction> {
-        // Grab token ID mint authority
-        let token_mint_authority =
-            self.get_token_mint_authority(&token_attrs.to_token_id()).await?;
+    pub async fn freeze_token(&self, token_id: TokenId) -> Result<Transaction> {
+        // Grab token ID mint authority and attribtes
+        let token_mint_authority = self.get_token_mint_authority(&token_id).await?;
+        let token_attrs =
+            self.derive_token_attributes(token_mint_authority.1, token_mint_authority.2);
         let mint_authority = Keypair::new(token_mint_authority.1);
         let mint_authority = Keypair::new(token_mint_authority.1);
 
 
+        // Sanity check
+        assert_eq!(token_id, token_attrs.to_token_id());
+
+        // Now we need to do a lookup for the zkas proof bincodes, and create
+        // the circuit objects and proving keys so we can build the transaction.
+        // We also do this through the RPC.
         let zkas_bins = self.lookup_zkas(&MONEY_CONTRACT_ID).await?;
         let zkas_bins = self.lookup_zkas(&MONEY_CONTRACT_ID).await?;
 
 
         let Some(auth_mint_zkbin) =
         let Some(auth_mint_zkbin) =
@@ -355,31 +349,61 @@ impl Drk {
             return Err(Error::Custom("Auth token mint circuit not found".to_string()))
             return Err(Error::Custom("Auth token mint circuit not found".to_string()))
         };
         };
 
 
+        let Some(fee_zkbin) = zkas_bins.iter().find(|x| x.0 == MONEY_CONTRACT_ZKAS_FEE_NS_V1)
+        else {
+            return Err(Error::Custom("Fee circuit not found".to_string()))
+        };
+
         let auth_mint_zkbin = ZkBinary::decode(&auth_mint_zkbin.1)?;
         let auth_mint_zkbin = ZkBinary::decode(&auth_mint_zkbin.1)?;
+        let fee_zkbin = ZkBinary::decode(&fee_zkbin.1)?;
+
         let auth_mint_circuit =
         let auth_mint_circuit =
             ZkCircuit::new(empty_witnesses(&auth_mint_zkbin)?, &auth_mint_zkbin);
             ZkCircuit::new(empty_witnesses(&auth_mint_zkbin)?, &auth_mint_zkbin);
+        let fee_circuit = ZkCircuit::new(empty_witnesses(&fee_zkbin)?, &fee_zkbin);
 
 
-        println!("Creating auth token mint circuit proving keys");
+        // Creating AuthTokenMint and Fee circuits proving keys
         let auth_mint_pk = ProvingKey::build(auth_mint_zkbin.k, &auth_mint_circuit);
         let auth_mint_pk = ProvingKey::build(auth_mint_zkbin.k, &auth_mint_circuit);
-        let freeze_builder = AuthTokenFreezeCallBuilder {
+        let fee_pk = ProvingKey::build(fee_zkbin.k, &fee_circuit);
+
+        // Create the freeze call
+        let builder = AuthTokenFreezeCallBuilder {
             mint_keypair: mint_authority,
             mint_keypair: mint_authority,
             token_attrs,
             token_attrs,
             auth_mint_zkbin,
             auth_mint_zkbin,
             auth_mint_pk,
             auth_mint_pk,
         };
         };
+        let freeze_debris = builder.build()?;
+        let mut data = vec![MoneyFunction::AuthTokenFreezeV1 as u8];
+        freeze_debris.params.encode_async(&mut data).await?;
+        let freeze_call = ContractCall { contract_id: *MONEY_CONTRACT_ID, data };
 
 
-        println!("Building transaction parameters");
-        let debris = freeze_builder.build()?;
+        // Create the TransactionBuilder containing above call
+        let mut tx_builder = TransactionBuilder::new(
+            ContractCallLeaf { call: freeze_call, proofs: freeze_debris.proofs },
+            vec![],
+        )?;
 
 
-        // Encode and sign the transaction
-        let mut data = vec![MoneyFunction::AuthTokenFreezeV1 as u8];
-        debris.params.encode_async(&mut data).await?;
-        let call = ContractCall { contract_id: *MONEY_CONTRACT_ID, data };
-        let mut tx_builder =
-            TransactionBuilder::new(ContractCallLeaf { call, proofs: debris.proofs }, vec![])?;
+        // We first have to execute the fee-less tx to gather its used gas, and then we feed
+        // it into the fee-creating function.
         let mut tx = tx_builder.build()?;
         let mut tx = tx_builder.build()?;
         let sigs = tx.create_sigs(&[mint_authority.secret])?;
         let sigs = tx.create_sigs(&[mint_authority.secret])?;
-        tx.signatures = vec![sigs];
+        tx.signatures.push(sigs);
+
+        let tree = self.get_money_tree().await?;
+        let secret = self.default_secret().await?;
+        let fee_public = PublicKey::from_secret(secret);
+        let (fee_call, fee_proofs, fee_secrets) =
+            self.append_fee_call(&tx, fee_public, &tree, &fee_pk, &fee_zkbin, None).await?;
+
+        // Append the fee call to the transaction
+        tx_builder.append(ContractCallLeaf { call: fee_call, proofs: fee_proofs }, vec![])?;
+
+        // Now build the actual transaction and sign it with all necessary keys.
+        let mut tx = tx_builder.build()?;
+        let sigs = tx.create_sigs(&[mint_authority.secret])?;
+        tx.signatures.push(sigs);
+        let sigs = tx.create_sigs(&fee_secrets)?;
+        tx.signatures.push(sigs);
 
 
         Ok(tx)
         Ok(tx)
     }
     }

+ 2 - 2
src/contract/money/src/client/auth_token_freeze_v1.rs

@@ -22,7 +22,7 @@ use darkfi::{
     Result,
     Result,
 };
 };
 use darkfi_sdk::crypto::Keypair;
 use darkfi_sdk::crypto::Keypair;
-use log::info;
+use log::debug;
 use rand::rngs::OsRng;
 use rand::rngs::OsRng;
 
 
 use crate::model::{MoneyAuthTokenFreezeParamsV1, TokenAttributes};
 use crate::model::{MoneyAuthTokenFreezeParamsV1, TokenAttributes};
@@ -45,7 +45,7 @@ pub struct AuthTokenFreezeCallBuilder {
 
 
 impl AuthTokenFreezeCallBuilder {
 impl AuthTokenFreezeCallBuilder {
     pub fn build(&self) -> Result<AuthTokenFreezeCallDebris> {
     pub fn build(&self) -> Result<AuthTokenFreezeCallDebris> {
-        info!("Building Money::AuthTokenFreezeV1 contract call");
+        debug!("Building Money::AuthTokenFreezeV1 contract call");
 
 
         // For the AuthTokenFreeze call, we just need to produce a valid signature,
         // For the AuthTokenFreeze call, we just need to produce a valid signature,
         // and enforce the correct derivation inside ZK.
         // and enforce the correct derivation inside ZK.

+ 2 - 2
src/contract/money/src/entrypoint/auth_token_freeze_v1.rs

@@ -77,7 +77,7 @@ pub(crate) fn money_auth_token_freeze_process_instruction_v1(
 
 
     // Check that the mint is not frozen
     // Check that the mint is not frozen
     if wasm::db::db_contains_key(token_freeze_db, &serialize(&params.token_id))? {
     if wasm::db::db_contains_key(token_freeze_db, &serialize(&params.token_id))? {
-        msg!("[MintV1] Error: Token mint for {} is frozen", params.token_id);
+        msg!("[AuthTokenFreezeV1] Error: Token mint for {} is frozen", params.token_id);
         return Err(MoneyError::TokenMintFrozen.into())
         return Err(MoneyError::TokenMintFrozen.into())
     }
     }
 
 
@@ -96,7 +96,7 @@ pub(crate) fn money_auth_token_freeze_process_update_v1(
     update: MoneyAuthTokenFreezeUpdateV1,
     update: MoneyAuthTokenFreezeUpdateV1,
 ) -> ContractResult {
 ) -> ContractResult {
     let token_freeze_db = wasm::db::db_lookup(cid, MONEY_CONTRACT_TOKEN_FREEZE_TREE)?;
     let token_freeze_db = wasm::db::db_lookup(cid, MONEY_CONTRACT_TOKEN_FREEZE_TREE)?;
-    msg!("[MintV1] Freezing mint for token {}", update.token_id);
+    msg!("[AuthTokenFreezeV1] Freezing mint for token {}", update.token_id);
     wasm::db::db_set(token_freeze_db, &serialize(&update.token_id), &[])?;
     wasm::db::db_set(token_freeze_db, &serialize(&update.token_id), &[])?;
 
 
     Ok(())
     Ok(())

+ 5 - 5
src/contract/money/src/entrypoint/token_mint_v1.rs

@@ -46,7 +46,7 @@ pub(crate) fn money_token_mint_get_metadata_v1(
     // Grab the auth call info
     // Grab the auth call info
     if self_.children_indexes.len() != 1 {
     if self_.children_indexes.len() != 1 {
         msg!(
         msg!(
-            "[MintV1] Error: Children indexes length is not expected(1): {}",
+            "[TokenMintV1] Error: Children indexes length is not expected(1): {}",
             self_.children_indexes.len()
             self_.children_indexes.len()
         );
         );
         return Err(MoneyError::ChildrenIndexesLengthMismatch.into())
         return Err(MoneyError::ChildrenIndexesLengthMismatch.into())
@@ -94,7 +94,7 @@ pub(crate) fn money_token_mint_process_instruction_v1(
 
 
     // Check that the coin from the output hasn't existed before
     // Check that the coin from the output hasn't existed before
     if wasm::db::db_contains_key(coins_db, &serialize(&params.coin))? {
     if wasm::db::db_contains_key(coins_db, &serialize(&params.coin))? {
-        msg!("[MintV1] Error: Duplicate coin in output");
+        msg!("[TokenMintV1] Error: Duplicate coin in output");
         return Err(MoneyError::DuplicateCoin.into())
         return Err(MoneyError::DuplicateCoin.into())
     }
     }
 
 
@@ -120,7 +120,7 @@ pub(crate) fn money_token_mint_process_update_v1(
     let nullifier_roots_db = wasm::db::db_lookup(cid, MONEY_CONTRACT_NULLIFIER_ROOTS_TREE)?;
     let nullifier_roots_db = wasm::db::db_lookup(cid, MONEY_CONTRACT_NULLIFIER_ROOTS_TREE)?;
 
 
     // This will just make a snapshot to match the coins one
     // This will just make a snapshot to match the coins one
-    msg!("[MintV1] Updating nullifiers snapshot");
+    msg!("[TokenMintV1] Updating nullifiers snapshot");
     wasm::merkle::sparse_merkle_insert_batch(
     wasm::merkle::sparse_merkle_insert_batch(
         info_db,
         info_db,
         nullifiers_db,
         nullifiers_db,
@@ -129,10 +129,10 @@ pub(crate) fn money_token_mint_process_update_v1(
         &vec![],
         &vec![],
     )?;
     )?;
 
 
-    msg!("[MintV1] Adding new coin to the set");
+    msg!("[TokenMintV1] Adding new coin to the set");
     wasm::db::db_set(coins_db, &serialize(&update.coin), &[])?;
     wasm::db::db_set(coins_db, &serialize(&update.coin), &[])?;
 
 
-    msg!("[MintV1] Adding new coin to the Merkle tree");
+    msg!("[TokenMintV1] Adding new coin to the Merkle tree");
     let coins = vec![MerkleNode::from(update.coin.inner())];
     let coins = vec![MerkleNode::from(update.coin.inner())];
     wasm::merkle::merkle_add(
     wasm::merkle::merkle_add(
         info_db,
         info_db,