drk: fixed token freezing and added its fee call

This commit is contained in:
skoupidi
2024-05-16 14:14:14 +03:00
parent f52b4573e9
commit c37618f354
6 changed files with 79 additions and 57 deletions

View File

@@ -1659,7 +1659,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> 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<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(())
}
},

View File

@@ -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");

View File

@@ -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<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);
// 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)
}

View File

@@ -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<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,
// and enforce the correct derivation inside ZK.

View File

@@ -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(&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())
}
@@ -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(())

View File

@@ -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(&params.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,