Kaynağa Gözat

script/research/gg: GenerateTx added to create genesis mint txs

skoupidi 2 yıl önce
ebeveyn
işleme
7e6a9a937b
2 değiştirilmiş dosya ile 97 ekleme ve 14 silme
  1. 3 1
      script/research/gg/Cargo.toml
  2. 94 13
      script/research/gg/src/main.rs

+ 3 - 1
script/research/gg/Cargo.toml

@@ -15,12 +15,14 @@ edition = "2021"
 [dependencies]
 # Darkfi
 darkfi = {path = "../../../", features = ["validator"]}
+darkfi_money_contract = {path = "../../../src/contract/money", features = ["no-entrypoint", "client"]}
 darkfi-contract-test-harness = {path = "../../../src/contract/test-harness"}
+darkfi-sdk = {path = "../../../src/sdk"}
 darkfi-serial = {path = "../../../src/serial"}
 
 # Misc
-anyhow = "1.0.80"
 async-std = {version = "1.12.0", features = ["attributes"]}
+bs58 = "0.5.0"
 clap = {version = "4.5.2", features = ["derive"]}
 sled = "0.34.7"
 

+ 94 - 13
script/research/gg/src/main.rs

@@ -18,20 +18,32 @@
 
 use std::{
     fs::{read_dir, read_to_string},
-    io::{stdin, Read},
+    io::{stdin, Cursor, Read},
+    process::exit,
+    str::FromStr,
 };
 
-use anyhow::Result;
 use clap::{Parser, Subcommand};
 use darkfi::{
     blockchain::{BlockInfo, Blockchain, BlockchainOverlay},
     cli_desc,
-    tx::Transaction,
-    util::{encoding::base64, path::expand_path, time::Timestamp},
-    validator::verification::verify_genesis_block,
+    tx::{ContractCallLeaf, Transaction, TransactionBuilder},
+    util::{encoding::base64, parse::decode_base10, path::expand_path, time::Timestamp},
+    validator::{utils::deploy_native_contracts, verification::verify_genesis_block},
+    zk::{empty_witnesses, halo2::Field, ProvingKey, ZkCircuit},
+    zkas::ZkBinary,
+    Result,
 };
 use darkfi_contract_test_harness::vks;
-use darkfi_serial::{deserialize, serialize};
+use darkfi_money_contract::{
+    client::genesis_mint_v1::GenesisMintCallBuilder, MoneyFunction, MONEY_CONTRACT_ZKAS_MINT_NS_V1,
+};
+use darkfi_sdk::{
+    crypto::{contract_id::MONEY_CONTRACT_ID, FuncId, Keypair, SecretKey},
+    pasta::pallas,
+    ContractCall,
+};
+use darkfi_serial::{deserialize, serialize, AsyncEncodable};
 
 #[derive(Parser)]
 #[command(about = cli_desc!())]
@@ -58,11 +70,18 @@ enum Subcmd {
 
     /// Read a Darkfi genesis block from stdin and verify it
     Verify,
+
+    /// Generate a Darkfi genesis transaction using the secret
+    /// key from  stdin
+    GenerateTx {
+        /// Amount to mint for this genesis transaction
+        amount: String,
+    },
 }
 
 /// Auxiliary function to read a bs58 genesis block from stdin
 fn read_block() -> Result<BlockInfo> {
-    eprintln!("Reading genesis block from stdin...");
+    println!("Reading genesis block from stdin...");
     let mut buf = String::new();
     stdin().read_to_string(&mut buf)?;
     let bytes = base64::decode(buf.trim()).unwrap();
@@ -80,7 +99,6 @@ async fn main() -> Result<()> {
         Subcmd::Display => {
             let genesis_block = read_block()?;
             println!("{genesis_block:#?}");
-            Ok(())
         }
 
         Subcmd::Generate { txs_folder, genesis_timestamp } => {
@@ -88,7 +106,12 @@ async fn main() -> Result<()> {
             let txs_folder = expand_path(&txs_folder).unwrap();
             let mut genesis_txs: Vec<Transaction> = vec![];
             for file in read_dir(txs_folder)? {
-                let bytes = base64::decode(read_to_string(file?.path())?.trim()).unwrap();
+                let file = file?;
+                let Ok(bytes) = bs58::decode(&read_to_string(file.path())?.trim()).into_vec()
+                else {
+                    eprintln!("Error: Failed to decode transaction: {:?}", file.path());
+                    exit(2);
+                };
                 let tx = deserialize(&bytes)?;
                 genesis_txs.push(tx);
             }
@@ -98,7 +121,7 @@ async fn main() -> Result<()> {
 
             // Update timestamp if one was provided
             if let Some(timestamp) = genesis_timestamp {
-                genesis_block.header.timestamp = Timestamp(timestamp);
+                genesis_block.header.timestamp = Timestamp::from_u64(timestamp);
             }
 
             // Retrieve genesis producer transaction
@@ -113,8 +136,6 @@ async fn main() -> Result<()> {
             // Write generated genesis block to stdin
             let encoded = base64::encode(&serialize(&genesis_block));
             println!("{encoded}");
-
-            Ok(())
         }
 
         Subcmd::Verify => {
@@ -131,12 +152,72 @@ async fn main() -> Result<()> {
             // Create an overlay over whole blockchain
             let blockchain = Blockchain::new(&sled_db)?;
             let overlay = BlockchainOverlay::new(&blockchain)?;
+            deploy_native_contracts(&overlay).await?;
 
             verify_genesis_block(&overlay, &genesis_block).await?;
 
             println!("Genesis block {hash} verified successfully!");
+        }
 
-            Ok(())
+        Subcmd::GenerateTx { amount } => {
+            let mut buf = String::new();
+            stdin().read_to_string(&mut buf)?;
+            let Ok(bytes) = bs58::decode(&buf.trim()).into_vec() else {
+                eprintln!("Error: Failed to decode stdin buffer");
+                exit(2);
+            };
+            let secret = deserialize::<SecretKey>(&bytes)?;
+            let keypair = Keypair::new(secret);
+
+            if let Err(e) = f64::from_str(&amount) {
+                eprintln!("Invalid amount: {e:?}");
+                exit(2);
+            }
+            let amount = decode_base10(&amount, 8, false)?;
+
+            // Grab mint proving keys and zkbin
+            let (pks, _) = vks::get_cached_pks_and_vks()?;
+            let mut mint = None;
+            for (bincode, namespace, pk) in pks {
+                if namespace.as_str() != MONEY_CONTRACT_ZKAS_MINT_NS_V1 {
+                    continue
+                }
+                let mut reader = Cursor::new(pk);
+                let zkbin = ZkBinary::decode(&bincode)?;
+                let circuit = ZkCircuit::new(empty_witnesses(&zkbin)?, &zkbin);
+                let proving_key = ProvingKey::read(&mut reader, circuit)?;
+                mint = Some((proving_key, zkbin));
+            }
+            let Some((mint_pk, mint_zkbin)) = mint else {
+                eprintln!("Mint proving keys not found.");
+                exit(2);
+            };
+
+            // Build the contract call
+            let builder = GenesisMintCallBuilder {
+                keypair,
+                amount,
+                spend_hook: FuncId::none(),
+                user_data: pallas::Base::ZERO,
+                mint_zkbin,
+                mint_pk,
+            };
+
+            let debris = builder.build()?;
+
+            // Encode and build the transaction
+            let mut data = vec![MoneyFunction::GenesisMintV1 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![])?;
+            let mut tx = tx_builder.build()?;
+            let sigs = tx.create_sigs(&[keypair.secret])?;
+            tx.signatures = vec![sigs];
+
+            println!("{}", bs58::encode(&serialize(&tx)).into_string());
         }
     }
+
+    Ok(())
 }