Explorar el Código

drk: Token mint freezing

parazyd hace 3 años
padre
commit
e67f133be8
Se han modificado 3 ficheros con 84 adiciones y 4 borrados
  1. 16 1
      bin/drk/src/main.rs
  2. 52 2
      bin/drk/src/rpc_token.rs
  3. 16 1
      bin/drk/src/wallet_money.rs

+ 16 - 1
bin/drk/src/main.rs

@@ -1206,7 +1206,22 @@ async fn main() -> Result<()> {
 
                 Ok(())
             }
-            TokenSubcmd::Freeze { token } => todo!(),
+
+            TokenSubcmd::Freeze { token } => {
+                let token_id =
+                    TokenId::try_from(token.as_str()).with_context(|| "Invalid token ID")?;
+
+                let drk = Drk::new(args.endpoint).await?;
+
+                let tx = drk
+                    .freeze_token(token_id)
+                    .await
+                    .with_context(|| "Failed to create token freeze transaction")?;
+
+                println!("{}", bs58::encode(&serialize(&tx)).into_string());
+
+                Ok(())
+            }
         },
     }
 }

+ 52 - 2
bin/drk/src/rpc_token.rs

@@ -24,7 +24,8 @@ use darkfi::{
     zkas::ZkBinary,
 };
 use darkfi_money_contract::{
-    client::mint_v1::MintCallBuilder, MoneyFunction, MONEY_CONTRACT_ZKAS_TOKEN_MINT_NS_V1,
+    client::{freeze_v1::FreezeCallBuilder, mint_v1::MintCallBuilder},
+    MoneyFunction, MONEY_CONTRACT_ZKAS_TOKEN_FRZ_NS_V1, MONEY_CONTRACT_ZKAS_TOKEN_MINT_NS_V1,
 };
 use darkfi_sdk::{
     crypto::{contract_id::MONEY_CONTRACT_ID, Keypair, PublicKey, TokenId},
@@ -37,7 +38,7 @@ use rand::rngs::OsRng;
 use super::Drk;
 
 impl Drk {
-    /// Create a payment transaction. Returns the transaction object on success.
+    /// Create a token mint transaction. Returns the transaction object on success.
     pub async fn mint_token(
         &self,
         amount: &str,
@@ -103,4 +104,53 @@ impl Drk {
 
         Ok(tx)
     }
+
+    /// Create a token freeze transaction. Returns the transaction object on success.
+    pub async fn freeze_token(&self, token_id: TokenId) -> Result<Transaction> {
+        let mut tokens = self.list_tokens().await?;
+        tokens.retain(|x| x.0 == token_id);
+        if tokens.is_empty() {
+            return Err(anyhow!("Did not find mint authority for token ID {}", token_id))
+        }
+        assert!(tokens.len() == 1);
+
+        let mint_authority = Keypair::new(tokens[0].1);
+
+        if tokens[0].2 {
+            return Err(anyhow!("This token is already marked as frozen in the wallet"))
+        }
+
+        let zkas_bins = self.lookup_zkas(&MONEY_CONTRACT_ID).await?;
+        let zkas_ns = MONEY_CONTRACT_ZKAS_TOKEN_FRZ_NS_V1;
+
+        let Some(token_freeze_zkbin) = zkas_bins.iter().find(|x| x.0 == zkas_ns) else {
+            return Err(anyhow!("Token freeze circuit not found"))
+        };
+
+        let k = 13;
+        let token_freeze_zkbin = ZkBinary::decode(&token_freeze_zkbin.1)?;
+        let token_freeze_circuit =
+            ZkCircuit::new(empty_witnesses(&token_freeze_zkbin), token_freeze_zkbin.clone());
+
+        eprintln!("Creating token freeze circuit proving keys");
+        let freeze_builder = FreezeCallBuilder {
+            mint_authority,
+            token_freeze_zkbin,
+            token_freeze_pk: ProvingKey::build(k, &token_freeze_circuit),
+        };
+
+        eprintln!("Building transaction parameters");
+        let debris = freeze_builder.build()?;
+
+        // Encode and sign the transaction
+        let mut data = vec![MoneyFunction::FreezeV1 as u8];
+        debris.params.encode(&mut data)?;
+        let calls = vec![ContractCall { contract_id: *MONEY_CONTRACT_ID, data }];
+        let proofs = vec![debris.proofs];
+        let mut tx = Transaction { calls, proofs, signatures: vec![] };
+        let sigs = tx.create_sigs(&mut OsRng, &[mint_authority.secret])?;
+        tx.signatures = vec![sigs];
+
+        Ok(tx)
+    }
 }

+ 16 - 1
bin/drk/src/wallet_money.rs

@@ -31,7 +31,7 @@ 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::{MoneyMintParamsV1, MoneyTransferParamsV1, Output},
+    model::{MoneyFreezeParamsV1, MoneyMintParamsV1, MoneyTransferParamsV1, Output},
     MoneyFunction,
 };
 use darkfi_sdk::{
@@ -486,6 +486,7 @@ impl Drk {
 
         let mut nullifiers: Vec<Nullifier> = vec![];
         let mut outputs: Vec<Output> = vec![];
+        let mut freezes: Vec<TokenId> = vec![];
 
         for (i, call) in tx.calls.iter().enumerate() {
             if call.contract_id == cid && call.data[0] == MoneyFunction::TransferV1 as u8 {
@@ -526,6 +527,16 @@ impl Drk {
 
                 continue
             }
+
+            if call.contract_id == cid && call.data[0] == MoneyFunction::FreezeV1 as u8 {
+                eprintln!("Found Money::FreezeV1 in call {}", i);
+                let params: MoneyFreezeParamsV1 = deserialize(&call.data[1..])?;
+
+                let (mint_x, mint_y) = params.signature_public.xy();
+                let token_id = TokenId::from(poseidon_hash([mint_x, mint_y]));
+
+                freezes.push(token_id);
+            }
         }
 
         let secrets = self.get_money_secrets().await?;
@@ -625,6 +636,10 @@ impl Drk {
             let _ = self.rpc_client.request(req).await?;
         }
 
+        for token_id in freezes {
+            // TODO: Update info in wallet if token id is found
+        }
+
         if !owncoins.is_empty() {
             if let Err(_) = kaching().await {
                 return Ok(())