diff --git a/bin/drk/src/main.rs b/bin/drk/src/main.rs index ee5a9faf0..ba2ec0d4a 100644 --- a/bin/drk/src/main.rs +++ b/bin/drk/src/main.rs @@ -1659,7 +1659,7 @@ async fn realmain(args: Args, ex: Arc>) -> Result<()> { TokenSubcmd::Freeze { token } => { let drk = 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, Err(e) => { eprintln!("Invalid Token ID: {e:?}"); @@ -1667,18 +1667,17 @@ async fn realmain(args: Args, ex: Arc>) -> 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(()) } }, diff --git a/bin/drk/src/money.rs b/bin/drk/src/money.rs index 579fe3c29..fd2928c93 100644 --- a/bin/drk/src/money.rs +++ b/bin/drk/src/money.rs @@ -754,8 +754,7 @@ impl Drk { MoneyFunction::AuthTokenFreezeV1 => { println!("[parse_money_call] Found Money::AuthTokenFreezeV1 call"); 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 => { println!("[parse_money_call] Found Money::TokenMintV1 call"); diff --git a/bin/drk/src/token.rs b/bin/drk/src/token.rs index 59ad2cde4..d7fe7ba85 100644 --- a/bin/drk/src/token.rs +++ b/bin/drk/src/token.rs @@ -213,10 +213,15 @@ impl Drk { // Decode provided amount 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_attrs = + self.derive_token_attributes(token_mint_authority.1, token_mint_authority.2); 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. @@ -253,24 +258,6 @@ impl Drk { let auth_mint_pk = ProvingKey::build(auth_mint_zkbin.k, &auth_mint_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 let coin_attrs = CoinAttributes { public_key: recipient, @@ -341,12 +328,19 @@ impl Drk { } /// Create a token freeze transaction. Returns the transaction object on success. - pub async fn freeze_token(&self, token_attrs: TokenAttributes) -> Result { - // 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 { + // 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); + // 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 Some(auth_mint_zkbin) = @@ -355,31 +349,61 @@ impl Drk { 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 fee_zkbin = ZkBinary::decode(&fee_zkbin.1)?; + let auth_mint_circuit = 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 freeze_builder = AuthTokenFreezeCallBuilder { + let fee_pk = ProvingKey::build(fee_zkbin.k, &fee_circuit); + + // Create the freeze call + let builder = AuthTokenFreezeCallBuilder { mint_keypair: mint_authority, token_attrs, auth_mint_zkbin, auth_mint_pk, }; - - println!("Building transaction parameters"); - let debris = freeze_builder.build()?; - - // Encode and sign the transaction + let freeze_debris = builder.build()?; 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![])?; + freeze_debris.params.encode_async(&mut data).await?; + let freeze_call = ContractCall { contract_id: *MONEY_CONTRACT_ID, data }; + + // Create the TransactionBuilder containing above call + let mut tx_builder = TransactionBuilder::new( + ContractCallLeaf { call: freeze_call, proofs: freeze_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 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) } diff --git a/src/contract/money/src/client/auth_token_freeze_v1.rs b/src/contract/money/src/client/auth_token_freeze_v1.rs index 021af3a96..b09ee774d 100644 --- a/src/contract/money/src/client/auth_token_freeze_v1.rs +++ b/src/contract/money/src/client/auth_token_freeze_v1.rs @@ -22,7 +22,7 @@ use darkfi::{ Result, }; use darkfi_sdk::crypto::Keypair; -use log::info; +use log::debug; use rand::rngs::OsRng; use crate::model::{MoneyAuthTokenFreezeParamsV1, TokenAttributes}; @@ -45,7 +45,7 @@ pub struct AuthTokenFreezeCallBuilder { impl AuthTokenFreezeCallBuilder { pub fn build(&self) -> Result { - info!("Building Money::AuthTokenFreezeV1 contract call"); + debug!("Building Money::AuthTokenFreezeV1 contract call"); // For the AuthTokenFreeze call, we just need to produce a valid signature, // and enforce the correct derivation inside ZK. diff --git a/src/contract/money/src/entrypoint/auth_token_freeze_v1.rs b/src/contract/money/src/entrypoint/auth_token_freeze_v1.rs index 38e070683..38c3b58b9 100644 --- a/src/contract/money/src/entrypoint/auth_token_freeze_v1.rs +++ b/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 if wasm::db::db_contains_key(token_freeze_db, &serialize(¶ms.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()) } @@ -96,7 +96,7 @@ pub(crate) fn money_auth_token_freeze_process_update_v1( update: MoneyAuthTokenFreezeUpdateV1, ) -> ContractResult { 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), &[])?; Ok(()) diff --git a/src/contract/money/src/entrypoint/token_mint_v1.rs b/src/contract/money/src/entrypoint/token_mint_v1.rs index 7ce393a7c..f7f7ba7b1 100644 --- a/src/contract/money/src/entrypoint/token_mint_v1.rs +++ b/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 if self_.children_indexes.len() != 1 { msg!( - "[MintV1] Error: Children indexes length is not expected(1): {}", + "[TokenMintV1] Error: Children indexes length is not expected(1): {}", self_.children_indexes.len() ); 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 if wasm::db::db_contains_key(coins_db, &serialize(¶ms.coin))? { - msg!("[MintV1] Error: Duplicate coin in output"); + msg!("[TokenMintV1] Error: Duplicate coin in output"); 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)?; // 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( info_db, nullifiers_db, @@ -129,10 +129,10 @@ pub(crate) fn money_token_mint_process_update_v1( &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), &[])?; - 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())]; wasm::merkle::merkle_add( info_db,