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

This commit is contained in:
skoupidi
2024-03-26 03:31:04 +02:00
parent 4d74247c9f
commit 7e6a9a937b
2 changed files with 97 additions and 14 deletions

View File

@@ -15,12 +15,14 @@ edition = "2021"
[dependencies] [dependencies]
# Darkfi # Darkfi
darkfi = {path = "../../../", features = ["validator"]} 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-contract-test-harness = {path = "../../../src/contract/test-harness"}
darkfi-sdk = {path = "../../../src/sdk"}
darkfi-serial = {path = "../../../src/serial"} darkfi-serial = {path = "../../../src/serial"}
# Misc # Misc
anyhow = "1.0.80"
async-std = {version = "1.12.0", features = ["attributes"]} async-std = {version = "1.12.0", features = ["attributes"]}
bs58 = "0.5.0"
clap = {version = "4.5.2", features = ["derive"]} clap = {version = "4.5.2", features = ["derive"]}
sled = "0.34.7" sled = "0.34.7"

View File

@@ -18,20 +18,32 @@
use std::{ use std::{
fs::{read_dir, read_to_string}, 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 clap::{Parser, Subcommand};
use darkfi::{ use darkfi::{
blockchain::{BlockInfo, Blockchain, BlockchainOverlay}, blockchain::{BlockInfo, Blockchain, BlockchainOverlay},
cli_desc, cli_desc,
tx::Transaction, tx::{ContractCallLeaf, Transaction, TransactionBuilder},
util::{encoding::base64, path::expand_path, time::Timestamp}, util::{encoding::base64, parse::decode_base10, path::expand_path, time::Timestamp},
validator::verification::verify_genesis_block, 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_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)] #[derive(Parser)]
#[command(about = cli_desc!())] #[command(about = cli_desc!())]
@@ -58,11 +70,18 @@ enum Subcmd {
/// Read a Darkfi genesis block from stdin and verify it /// Read a Darkfi genesis block from stdin and verify it
Verify, 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 /// Auxiliary function to read a bs58 genesis block from stdin
fn read_block() -> Result<BlockInfo> { fn read_block() -> Result<BlockInfo> {
eprintln!("Reading genesis block from stdin..."); println!("Reading genesis block from stdin...");
let mut buf = String::new(); let mut buf = String::new();
stdin().read_to_string(&mut buf)?; stdin().read_to_string(&mut buf)?;
let bytes = base64::decode(buf.trim()).unwrap(); let bytes = base64::decode(buf.trim()).unwrap();
@@ -80,7 +99,6 @@ async fn main() -> Result<()> {
Subcmd::Display => { Subcmd::Display => {
let genesis_block = read_block()?; let genesis_block = read_block()?;
println!("{genesis_block:#?}"); println!("{genesis_block:#?}");
Ok(())
} }
Subcmd::Generate { txs_folder, genesis_timestamp } => { Subcmd::Generate { txs_folder, genesis_timestamp } => {
@@ -88,7 +106,12 @@ async fn main() -> Result<()> {
let txs_folder = expand_path(&txs_folder).unwrap(); let txs_folder = expand_path(&txs_folder).unwrap();
let mut genesis_txs: Vec<Transaction> = vec![]; let mut genesis_txs: Vec<Transaction> = vec![];
for file in read_dir(txs_folder)? { 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)?; let tx = deserialize(&bytes)?;
genesis_txs.push(tx); genesis_txs.push(tx);
} }
@@ -98,7 +121,7 @@ async fn main() -> Result<()> {
// Update timestamp if one was provided // Update timestamp if one was provided
if let Some(timestamp) = genesis_timestamp { if let Some(timestamp) = genesis_timestamp {
genesis_block.header.timestamp = Timestamp(timestamp); genesis_block.header.timestamp = Timestamp::from_u64(timestamp);
} }
// Retrieve genesis producer transaction // Retrieve genesis producer transaction
@@ -113,8 +136,6 @@ async fn main() -> Result<()> {
// Write generated genesis block to stdin // Write generated genesis block to stdin
let encoded = base64::encode(&serialize(&genesis_block)); let encoded = base64::encode(&serialize(&genesis_block));
println!("{encoded}"); println!("{encoded}");
Ok(())
} }
Subcmd::Verify => { Subcmd::Verify => {
@@ -131,12 +152,72 @@ async fn main() -> Result<()> {
// Create an overlay over whole blockchain // Create an overlay over whole blockchain
let blockchain = Blockchain::new(&sled_db)?; let blockchain = Blockchain::new(&sled_db)?;
let overlay = BlockchainOverlay::new(&blockchain)?; let overlay = BlockchainOverlay::new(&blockchain)?;
deploy_native_contracts(&overlay).await?;
verify_genesis_block(&overlay, &genesis_block).await?; verify_genesis_block(&overlay, &genesis_block).await?;
println!("Genesis block {hash} verified successfully!"); 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(())
} }