diff --git a/script/research/zkvm-metering/README.md b/script/research/zkvm-metering/README.md
index 6c96a21ac..62d2ed8da 100644
--- a/script/research/zkvm-metering/README.md
+++ b/script/research/zkvm-metering/README.md
@@ -64,3 +64,22 @@ Once the `heaptrack` report is generated you can view it using `heaptrack_gui`.
| 21 | range_check | 2.4 MB | 145.6 kB | 7.6 kB |
| 22 | witness_base | 2.4 MB | 145.6 kB | 7.6 kB |
| 23 | debug | 2.4 MB | 145.6 kB | 7.6 kB |
+
+#### Native Contracts' Proofs
+| # | Proof | RAM Usage | Verifying Key Size | Proof Size |
+|----|----------------------------------|-----------|--------------------|------------|
+| 0 | money_mint_v1 | 2.5 MB | 145.6 kB | 7.6 kB |
+| 1 | money_burn_v1 | 2.5 MB | 145.6 kB | 7.6 kB |
+| 2 | money_fee_v1 | 2.5 MB | 145.6 kB | 7.6 kB |
+| 3 | money_token_mint_v1 | 2.5 MB | 145.6 kB | 7.6 kB |
+| 4 | money_auth_token_mint_v1 | 2.4 MB | 145.6 kB | 7.6 kB |
+| 5 | dao_mint | 2.5 MB | 145.6 kB | 7.6 kB |
+| 6 | dao_propose_input | 17.2 MB | 1.2 MB | 7.7 kB |
+| 7 | dao_propose_main | 2.6 MB | 145.6 kB | 7.6 kB |
+| 8 | dao_vote_input | 17.2 MB | 1.2 MB | 7.7 kB |
+| 9 | dao_vote_main | 2.6 MB | 145.6 kB | 7.6 kB |
+| 10 | dao_exec | 2.6 MB | 145.6 kB | 7.6 kB |
+| 11 | dao_early_exec | 2.6 MB | 145.6 kB | 7.6 kB |
+| 12 | dao_auth_money_transfer | 2.6 MB | 145.6 kB | 7.6 kB |
+| 13 | dao_auth_money_transfer_enc_coin | 2.5 MB | 145.6 kB | 7.6 kB |
+
diff --git a/script/research/zkvm-metering/generator/src/dao/mod.rs b/script/research/zkvm-metering/generator/src/dao/mod.rs
new file mode 100644
index 000000000..58ac4be06
--- /dev/null
+++ b/script/research/zkvm-metering/generator/src/dao/mod.rs
@@ -0,0 +1,1016 @@
+/* This file is part of DarkFi (https://dark.fi)
+ *
+ * Copyright (C) 2020-2026 Dyne.org foundation
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+use darkfi::zk::{Witness, halo2::Field};
+use darkfi_sdk::{
+ crypto::{
+ BaseBlind, Blind, MerkleNode, MerkleTree, PublicKey, ScalarBlind, SecretKey,
+ note::ElGamalEncryptedNote,
+ pasta_prelude::{Curve, CurveAffine},
+ pedersen_commitment_u64,
+ smt::{EMPTY_NODES_FP, MemoryStorageFp, PoseidonFp, SmtMemoryFp},
+ util::{fv_mod_fp_unsafe, poseidon_hash},
+ },
+ pasta::{Fp, Fq, pallas, pallas::Base},
+};
+use halo2_proofs::circuit::Value;
+use rand::rngs::OsRng;
+
+pub fn mint() -> (Vec, Vec) {
+ let proposer_limit = Fp::from(20);
+ let quorum = Fp::from(10);
+ let early_exec_quorum = Fp::from(10);
+ let approval_ratio_quot = Fp::from(67);
+ let approval_ratio_base = Fp::from(100);
+
+ let dao_notes_secret_key = SecretKey::random(&mut OsRng);
+ let dao_proposer_secret_key = SecretKey::random(&mut OsRng);
+ let dao_proposals_secret_key = SecretKey::random(&mut OsRng);
+ let dao_votes_secret_key = SecretKey::random(&mut OsRng);
+ let dao_exec_secret_key = SecretKey::random(&mut OsRng);
+ let dao_early_exec_secret_key = SecretKey::random(&mut OsRng);
+
+ let dao_notes_pub_key = PublicKey::from_secret(dao_notes_secret_key);
+ let dao_proposer_pub_key = PublicKey::from_secret(dao_proposer_secret_key);
+ let dao_proposals_pub_key = PublicKey::from_secret(dao_proposals_secret_key);
+ let dao_votes_pub_key = PublicKey::from_secret(dao_votes_secret_key);
+ let dao_exec_pub_key = PublicKey::from_secret(dao_exec_secret_key);
+ let dao_early_exec_pub_key = PublicKey::from_secret(dao_early_exec_secret_key);
+
+ let gov_token_id = Fp::random(&mut OsRng);
+ let bulla_blind = Fp::random(&mut OsRng);
+
+ let bulla = poseidon_hash([
+ proposer_limit,
+ quorum,
+ early_exec_quorum,
+ approval_ratio_quot,
+ approval_ratio_base,
+ gov_token_id,
+ dao_notes_pub_key.x(),
+ dao_notes_pub_key.y(),
+ dao_proposer_pub_key.x(),
+ dao_proposer_pub_key.y(),
+ dao_proposals_pub_key.x(),
+ dao_proposals_pub_key.y(),
+ dao_votes_pub_key.x(),
+ dao_votes_pub_key.y(),
+ dao_exec_pub_key.x(),
+ dao_exec_pub_key.y(),
+ dao_early_exec_pub_key.x(),
+ dao_early_exec_pub_key.y(),
+ bulla_blind,
+ ]);
+
+ let prover_witnesses = vec![
+ Witness::Base(Value::known(proposer_limit)),
+ Witness::Base(Value::known(quorum)),
+ Witness::Base(Value::known(early_exec_quorum)),
+ Witness::Base(Value::known(approval_ratio_quot)),
+ Witness::Base(Value::known(approval_ratio_base)),
+ Witness::Base(Value::known(gov_token_id)),
+ Witness::Base(Value::known(dao_notes_secret_key.inner())),
+ Witness::Base(Value::known(dao_proposer_secret_key.inner())),
+ Witness::Base(Value::known(dao_proposals_secret_key.inner())),
+ Witness::Base(Value::known(dao_votes_secret_key.inner())),
+ Witness::Base(Value::known(dao_exec_secret_key.inner())),
+ Witness::Base(Value::known(dao_early_exec_secret_key.inner())),
+ Witness::Base(Value::known(bulla_blind)),
+ ];
+
+ let public_inputs = vec![dao_notes_pub_key.x(), dao_notes_pub_key.y(), bulla];
+
+ (prover_witnesses, public_inputs)
+}
+
+pub fn propose_input() -> (Vec, Vec) {
+ // Governance coin setup
+ let coin_secret = SecretKey::random(&mut OsRng);
+ let coin_pubkey = PublicKey::from_secret(coin_secret);
+ let coin_pub_x = coin_pubkey.x();
+ let coin_pub_y = coin_pubkey.y();
+
+ let sig_secret = SecretKey::random(&mut OsRng);
+ let sig_pubkey = PublicKey::from_secret(sig_secret);
+ let sig_pub_x = sig_pubkey.x();
+ let sig_pub_y = sig_pubkey.y();
+
+ let coin_value = 23u64;
+ let gov_token_id = Fp::random(&mut OsRng);
+ let coin_spend_hook = Fp::from(0);
+ let coin_user_data = Fp::from(0);
+ let coin_blind = BaseBlind::random(&mut OsRng);
+ let value_blind = ScalarBlind::random(&mut OsRng);
+ let gov_token_blind = BaseBlind::random(&mut OsRng);
+
+ let my_coin = poseidon_hash([
+ coin_pub_x,
+ coin_pub_y,
+ Fp::from(coin_value),
+ gov_token_id,
+ coin_spend_hook,
+ coin_user_data,
+ coin_blind.inner(),
+ ]);
+ let value_commit = (pedersen_commitment_u64(coin_value, value_blind)).to_affine();
+ let value_commit_x = *value_commit.coordinates().unwrap().x();
+ let value_commit_y = *value_commit.coordinates().unwrap().y();
+ let gov_token_commit = poseidon_hash([gov_token_id, gov_token_blind.inner()]);
+
+ // Merkle tree setup
+ let mut tree = MerkleTree::new(u32::MAX as usize);
+ let coin1 = MerkleNode::from(Fp::random(&mut OsRng));
+ let coin2 = MerkleNode::from(Fp::random(&mut OsRng));
+ tree.append(coin1);
+ tree.mark();
+ tree.append(MerkleNode::from(my_coin));
+ let leaf_position = tree.mark().unwrap();
+ tree.append(coin2);
+
+ let merkle_root = tree.root(0).unwrap().inner();
+ let merkle_path = tree.witness(leaf_position, 0).unwrap();
+ // Sparse merkle tree setup
+ let mut smt = SmtMemoryFp::new(MemoryStorageFp::new(), PoseidonFp::new(), &EMPTY_NODES_FP);
+
+ let leaves = vec![Fp::random(&mut OsRng), Fp::random(&mut OsRng), Fp::random(&mut OsRng)];
+ let leaves: Vec<_> = leaves.into_iter().map(|l| (l, l)).collect();
+ smt.insert_batch(leaves.clone()).unwrap();
+
+ let smt_null_root = smt.root();
+ let nullifier = poseidon_hash([coin_secret.inner(), my_coin]);
+
+ let smt_null_path = smt.prove_membership(&nullifier);
+ if !smt_null_path.verify(&smt_null_root, &pallas::Base::ZERO, &nullifier) {
+ panic!("smt null path verification_failed");
+ }
+
+ let prover_witnesses = vec![
+ Witness::Base(Value::known(coin_secret.inner())),
+ Witness::Base(Value::known(pallas::Base::from(coin_value))),
+ Witness::Base(Value::known(gov_token_id)),
+ Witness::Base(Value::known(coin_spend_hook)),
+ Witness::Base(Value::known(coin_user_data)),
+ Witness::Base(Value::known(coin_blind.inner())),
+ Witness::Scalar(Value::known(value_blind.inner())),
+ Witness::Base(Value::known(gov_token_blind.inner())),
+ Witness::Uint32(Value::known(u64::from(leaf_position).try_into().unwrap())),
+ Witness::MerklePath(Value::known(merkle_path.clone().try_into().unwrap())),
+ Witness::SparseMerklePath(Value::known(smt_null_path.path)),
+ Witness::Base(Value::known(sig_secret.inner())),
+ ];
+
+ let public_inputs = vec![
+ smt_null_root,
+ value_commit_x,
+ value_commit_y,
+ gov_token_commit,
+ merkle_root,
+ sig_pub_x,
+ sig_pub_y,
+ ];
+
+ (prover_witnesses, public_inputs)
+}
+
+pub fn propose_main() -> (Vec, Vec) {
+ let proposer_limit = Fp::from(20);
+ let quorum = Fp::from(10);
+ let early_exec_quorum = Fp::from(10);
+ let approval_ratio_quot = Fp::from(67);
+ let approval_ratio_base = Fp::from(100);
+
+ let dao_notes_secret_key = SecretKey::random(&mut OsRng);
+ let dao_proposer_secret_key = SecretKey::random(&mut OsRng);
+ let dao_proposals_secret_key = SecretKey::random(&mut OsRng);
+ let dao_votes_secret_key = SecretKey::random(&mut OsRng);
+ let dao_exec_secret_key = SecretKey::random(&mut OsRng);
+ let dao_early_exec_secret_key = SecretKey::random(&mut OsRng);
+
+ let dao_notes_pub_key = PublicKey::from_secret(dao_notes_secret_key);
+ let dao_proposer_pub_key = PublicKey::from_secret(dao_proposer_secret_key);
+ let dao_proposals_pub_key = PublicKey::from_secret(dao_proposals_secret_key);
+ let dao_votes_pub_key = PublicKey::from_secret(dao_votes_secret_key);
+ let dao_exec_pub_key = PublicKey::from_secret(dao_exec_secret_key);
+ let dao_early_exec_pub_key = PublicKey::from_secret(dao_early_exec_secret_key);
+
+ let gov_token_id = Fp::random(&mut OsRng);
+ let gov_token_blind = BaseBlind::random(&mut OsRng);
+ let gov_token_commit = poseidon_hash([gov_token_id, gov_token_blind.inner()]);
+ let bulla_blind = Fp::random(&mut OsRng);
+
+ let dao_bulla = poseidon_hash([
+ proposer_limit,
+ quorum,
+ early_exec_quorum,
+ approval_ratio_quot,
+ approval_ratio_base,
+ gov_token_id,
+ dao_notes_pub_key.x(),
+ dao_notes_pub_key.y(),
+ dao_proposer_pub_key.x(),
+ dao_proposer_pub_key.y(),
+ dao_proposals_pub_key.x(),
+ dao_proposals_pub_key.y(),
+ dao_votes_pub_key.x(),
+ dao_votes_pub_key.y(),
+ dao_exec_pub_key.x(),
+ dao_exec_pub_key.y(),
+ dao_early_exec_pub_key.x(),
+ dao_early_exec_pub_key.y(),
+ bulla_blind,
+ ]);
+
+ // Store Dao Bulla in Merkle tree
+ let mut tree = MerkleTree::new(u32::MAX as usize);
+ let coin1 = MerkleNode::from(Fp::random(&mut OsRng));
+ let coin2 = MerkleNode::from(Fp::random(&mut OsRng));
+ tree.append(coin1);
+ tree.mark();
+ tree.append(MerkleNode::from(dao_bulla));
+ let dao_leaf_position = tree.mark().unwrap();
+ tree.append(coin2);
+
+ let dao_merkle_root = tree.root(0).unwrap().inner();
+ let dao_merkle_path = tree.witness(dao_leaf_position, 0).unwrap();
+
+ // Proposal info
+ let proposal_blind = BaseBlind::random(&mut OsRng);
+ let proposal_auth_calls_commit = Fp::random(&mut OsRng);
+ let proposal_creation_blockwindow = Fp::from(100000);
+ let proposal_duration_blockwindows = Fp::from(20);
+ let proposal_bulla = poseidon_hash([
+ proposal_auth_calls_commit,
+ proposal_creation_blockwindow,
+ proposal_duration_blockwindows,
+ Fp::ZERO,
+ dao_bulla,
+ proposal_blind.inner(),
+ ]);
+
+ let total_funds = 2300;
+ let total_funds_blind = ScalarBlind::random(&mut OsRng);
+ let total_funds_commit = pedersen_commitment_u64(total_funds, total_funds_blind);
+ let total_funds_coords = total_funds_commit.to_affine().coordinates().unwrap();
+ let total_funds = pallas::Base::from(total_funds);
+
+ let prover_witnesses = vec![
+ // Proposers total number of gov tokens
+ Witness::Base(Value::known(total_funds)),
+ Witness::Scalar(Value::known(total_funds_blind.inner())),
+ // Used for blinding exported gov token ID
+ Witness::Base(Value::known(gov_token_blind.inner())),
+ // Proposal params
+ Witness::Base(Value::known(proposal_auth_calls_commit)),
+ Witness::Base(Value::known(proposal_creation_blockwindow)),
+ Witness::Base(Value::known(proposal_duration_blockwindows)),
+ Witness::Base(Value::known(Fp::ZERO)),
+ Witness::Base(Value::known(proposal_blind.inner())),
+ // DAO params
+ Witness::Base(Value::known(proposer_limit)),
+ Witness::Base(Value::known(quorum)),
+ Witness::Base(Value::known(early_exec_quorum)),
+ Witness::Base(Value::known(approval_ratio_quot)),
+ Witness::Base(Value::known(approval_ratio_base)),
+ Witness::Base(Value::known(gov_token_id)),
+ Witness::Base(Value::known(dao_notes_pub_key.x())),
+ Witness::Base(Value::known(dao_notes_pub_key.y())),
+ Witness::Base(Value::known(dao_proposer_secret_key.inner())),
+ Witness::Base(Value::known(dao_proposals_pub_key.x())),
+ Witness::Base(Value::known(dao_proposals_pub_key.y())),
+ Witness::Base(Value::known(dao_votes_pub_key.x())),
+ Witness::Base(Value::known(dao_votes_pub_key.y())),
+ Witness::Base(Value::known(dao_exec_pub_key.x())),
+ Witness::Base(Value::known(dao_exec_pub_key.y())),
+ Witness::Base(Value::known(dao_early_exec_pub_key.x())),
+ Witness::Base(Value::known(dao_early_exec_pub_key.y())),
+ Witness::Base(Value::known(bulla_blind)),
+ Witness::Uint32(Value::known(u64::from(dao_leaf_position).try_into().unwrap())),
+ Witness::MerklePath(Value::known(dao_merkle_path.try_into().unwrap())),
+ ];
+
+ let public_inputs = vec![
+ gov_token_commit,
+ dao_merkle_root,
+ proposal_bulla,
+ proposal_creation_blockwindow,
+ *total_funds_coords.x(),
+ *total_funds_coords.y(),
+ ];
+
+ (prover_witnesses, public_inputs)
+}
+
+pub fn vote_input() -> (Vec, Vec) {
+ // Governance coin setup
+ let coin_secret = SecretKey::random(&mut OsRng);
+ let coin_pubkey = PublicKey::from_secret(coin_secret);
+ let coin_pub_x = coin_pubkey.x();
+ let coin_pub_y = coin_pubkey.y();
+
+ let sig_secret = SecretKey::random(&mut OsRng);
+ let sig_pubkey = PublicKey::from_secret(sig_secret);
+ let sig_pub_x = sig_pubkey.x();
+ let sig_pub_y = sig_pubkey.y();
+
+ let coin_value = 23u64;
+ let gov_token_id = Fp::random(&mut OsRng);
+ let coin_spend_hook = Fp::from(0);
+ let coin_user_data = Fp::from(0);
+ let coin_blind = BaseBlind::random(&mut OsRng);
+ let value_blind = ScalarBlind::random(&mut OsRng);
+ let gov_token_blind = BaseBlind::random(&mut OsRng);
+
+ let my_coin = poseidon_hash([
+ coin_pub_x,
+ coin_pub_y,
+ Fp::from(coin_value),
+ gov_token_id,
+ coin_spend_hook,
+ coin_user_data,
+ coin_blind.inner(),
+ ]);
+ let value_commit = (pedersen_commitment_u64(coin_value, value_blind)).to_affine();
+ let value_commit_x = *value_commit.coordinates().unwrap().x();
+ let value_commit_y = *value_commit.coordinates().unwrap().y();
+ let gov_token_commit = poseidon_hash([gov_token_id, gov_token_blind.inner()]);
+
+ // Merkle tree setup
+ let mut tree = MerkleTree::new(u32::MAX as usize);
+ let coin1 = MerkleNode::from(Fp::random(&mut OsRng));
+ let coin2 = MerkleNode::from(Fp::random(&mut OsRng));
+ tree.append(coin1);
+ tree.mark();
+ tree.append(MerkleNode::from(my_coin));
+ let leaf_position = tree.mark().unwrap();
+ tree.append(coin2);
+
+ let merkle_root = tree.root(0).unwrap().inner();
+ let merkle_path = tree.witness(leaf_position, 0).unwrap();
+ // Sparse merkle tree setup
+ let mut smt = SmtMemoryFp::new(MemoryStorageFp::new(), PoseidonFp::new(), &EMPTY_NODES_FP);
+
+ let leaves = vec![Fp::random(&mut OsRng), Fp::random(&mut OsRng), Fp::random(&mut OsRng)];
+ let leaves: Vec<_> = leaves.into_iter().map(|l| (l, l)).collect();
+ smt.insert_batch(leaves.clone()).unwrap();
+
+ let smt_null_root = smt.root();
+ let nullifier = poseidon_hash([coin_secret.inner(), my_coin]);
+
+ let smt_null_path = smt.prove_membership(&nullifier);
+ if !smt_null_path.verify(&smt_null_root, &pallas::Base::ZERO, &nullifier) {
+ panic!("smt null path verification_failed");
+ }
+
+ let proposal_bulla = Fp::random(&mut OsRng);
+ let vote_nullifier = poseidon_hash([nullifier, coin_secret.inner(), proposal_bulla]);
+
+ let prover_witnesses = vec![
+ Witness::Base(Value::known(coin_secret.inner())),
+ Witness::Base(Value::known(pallas::Base::from(coin_value))),
+ Witness::Base(Value::known(gov_token_id)),
+ Witness::Base(Value::known(coin_spend_hook)),
+ Witness::Base(Value::known(coin_user_data)),
+ Witness::Base(Value::known(coin_blind.inner())),
+ Witness::Base(Value::known(proposal_bulla)),
+ Witness::Scalar(Value::known(value_blind.inner())),
+ Witness::Base(Value::known(gov_token_blind.inner())),
+ Witness::Uint32(Value::known(u64::from(leaf_position).try_into().unwrap())),
+ Witness::MerklePath(Value::known(merkle_path.clone().try_into().unwrap())),
+ Witness::SparseMerklePath(Value::known(smt_null_path.path)),
+ Witness::Base(Value::known(sig_secret.inner())),
+ ];
+
+ let public_inputs = vec![
+ smt_null_root,
+ proposal_bulla,
+ vote_nullifier,
+ value_commit_x,
+ value_commit_y,
+ gov_token_commit,
+ merkle_root,
+ sig_pub_x,
+ sig_pub_y,
+ ];
+
+ (prover_witnesses, public_inputs)
+}
+
+pub fn vote_main() -> (Vec, Vec) {
+ let proposer_limit = Fp::from(20);
+ let quorum = Fp::from(10);
+ let early_exec_quorum = Fp::from(10);
+ let approval_ratio_quot = Fp::from(67);
+ let approval_ratio_base = Fp::from(100);
+
+ let dao_notes_secret_key = SecretKey::random(&mut OsRng);
+ let dao_proposer_secret_key = SecretKey::random(&mut OsRng);
+ let dao_proposals_secret_key = SecretKey::random(&mut OsRng);
+ let dao_votes_secret_key = SecretKey::random(&mut OsRng);
+ let dao_exec_secret_key = SecretKey::random(&mut OsRng);
+ let dao_early_exec_secret_key = SecretKey::random(&mut OsRng);
+
+ let dao_notes_pub_key = PublicKey::from_secret(dao_notes_secret_key);
+ let dao_proposer_pub_key = PublicKey::from_secret(dao_proposer_secret_key);
+ let dao_proposals_pub_key = PublicKey::from_secret(dao_proposals_secret_key);
+ let dao_votes_pub_key = PublicKey::from_secret(dao_votes_secret_key);
+ let dao_exec_pub_key = PublicKey::from_secret(dao_exec_secret_key);
+ let dao_early_exec_pub_key = PublicKey::from_secret(dao_early_exec_secret_key);
+
+ let gov_token_id = Fp::random(&mut OsRng);
+ let gov_token_blind = BaseBlind::random(&mut OsRng);
+ let gov_token_commit = poseidon_hash([gov_token_id, gov_token_blind.inner()]);
+ let bulla_blind = Fp::random(&mut OsRng);
+
+ let dao_bulla = poseidon_hash([
+ proposer_limit,
+ quorum,
+ early_exec_quorum,
+ approval_ratio_quot,
+ approval_ratio_base,
+ gov_token_id,
+ dao_notes_pub_key.x(),
+ dao_notes_pub_key.y(),
+ dao_proposer_pub_key.x(),
+ dao_proposer_pub_key.y(),
+ dao_proposals_pub_key.x(),
+ dao_proposals_pub_key.y(),
+ dao_votes_pub_key.x(),
+ dao_votes_pub_key.y(),
+ dao_exec_pub_key.x(),
+ dao_exec_pub_key.y(),
+ dao_early_exec_pub_key.x(),
+ dao_early_exec_pub_key.y(),
+ bulla_blind,
+ ]);
+
+ // Proposal info
+ let proposal_blind = BaseBlind::random(&mut OsRng);
+ let proposal_auth_calls_commit = Fp::random(&mut OsRng);
+ let proposal_creation_blockwindow = Fp::from(100000);
+ let proposal_duration_blockwindows = Fp::from(20);
+ let proposal_bulla = poseidon_hash([
+ proposal_auth_calls_commit,
+ proposal_creation_blockwindow,
+ proposal_duration_blockwindows,
+ Fp::ZERO,
+ dao_bulla,
+ proposal_blind.inner(),
+ ]);
+
+ // Vote Info
+ let vote_option = 1u64;
+ let yes_vote_blind = loop {
+ let blind = pallas::Scalar::random(&mut OsRng);
+ if fv_mod_fp_unsafe(blind).is_some().into() {
+ break blind
+ }
+ };
+ let all_vote_blind = Fq::random(&mut OsRng);
+ let all_vote_value = 10000;
+
+ let yes_vote_commit =
+ pedersen_commitment_u64(vote_option * all_vote_value, Blind(yes_vote_blind));
+ let yes_vote_commit_coords = yes_vote_commit.to_affine().coordinates().unwrap();
+ let all_vote_commit = pedersen_commitment_u64(all_vote_value, Blind(all_vote_blind));
+ let all_vote_commit_coords = all_vote_commit.to_affine().coordinates().unwrap();
+
+ let yes_vote_blind = Blind(fv_mod_fp_unsafe(yes_vote_blind).unwrap());
+ let all_vote_blind = Blind(fv_mod_fp_unsafe(all_vote_blind).unwrap());
+
+ let vote_option = Fp::from(vote_option);
+ let all_vote_value_fp = Fp::from(all_vote_value);
+ let ephem_secret = SecretKey::random(&mut OsRng);
+ let ephem_pubkey = PublicKey::from_secret(ephem_secret);
+ let (ephem_x, ephem_y) = ephem_pubkey.xy();
+ let current_blockwindow = Fp::from(100005);
+
+ let note = [vote_option, yes_vote_blind.inner(), all_vote_value_fp, all_vote_blind.inner()];
+ let enc_note =
+ ElGamalEncryptedNote::encrypt_unsafe(note, &ephem_secret, &dao_votes_pub_key).unwrap();
+
+ let prover_witnesses = vec![
+ // Proposal params
+ Witness::Base(Value::known(proposal_auth_calls_commit)),
+ Witness::Base(Value::known(proposal_creation_blockwindow)),
+ Witness::Base(Value::known(proposal_duration_blockwindows)),
+ Witness::Base(Value::known(Fp::ZERO)),
+ Witness::Base(Value::known(proposal_blind.inner())),
+ // DAO params
+ Witness::Base(Value::known(proposer_limit)),
+ Witness::Base(Value::known(quorum)),
+ Witness::Base(Value::known(early_exec_quorum)),
+ Witness::Base(Value::known(approval_ratio_quot)),
+ Witness::Base(Value::known(approval_ratio_base)),
+ Witness::Base(Value::known(gov_token_id)),
+ Witness::Base(Value::known(dao_notes_pub_key.x())),
+ Witness::Base(Value::known(dao_notes_pub_key.y())),
+ Witness::Base(Value::known(dao_proposer_pub_key.x())),
+ Witness::Base(Value::known(dao_proposer_pub_key.y())),
+ Witness::Base(Value::known(dao_proposals_pub_key.x())),
+ Witness::Base(Value::known(dao_proposals_pub_key.y())),
+ Witness::EcNiPoint(Value::known(dao_votes_pub_key.inner())),
+ Witness::Base(Value::known(dao_exec_pub_key.x())),
+ Witness::Base(Value::known(dao_exec_pub_key.y())),
+ Witness::Base(Value::known(dao_early_exec_pub_key.x())),
+ Witness::Base(Value::known(dao_early_exec_pub_key.y())),
+ Witness::Base(Value::known(bulla_blind)),
+ // Vote
+ Witness::Base(Value::known(vote_option)),
+ Witness::Base(Value::known(yes_vote_blind.inner())),
+ // Total number of gov tokens allocated
+ Witness::Base(Value::known(all_vote_value_fp)),
+ Witness::Base(Value::known(all_vote_blind.inner())),
+ // Gov token
+ Witness::Base(Value::known(gov_token_blind.inner())),
+ // Time checks
+ Witness::Base(Value::known(current_blockwindow)),
+ // verifiable encryption
+ Witness::Base(Value::known(ephem_secret.inner())),
+ ];
+
+ let public_inputs = vec![
+ gov_token_commit,
+ proposal_bulla,
+ *yes_vote_commit_coords.x(),
+ *yes_vote_commit_coords.y(),
+ *all_vote_commit_coords.x(),
+ *all_vote_commit_coords.y(),
+ current_blockwindow,
+ ephem_x,
+ ephem_y,
+ enc_note.encrypted_values[0],
+ enc_note.encrypted_values[1],
+ enc_note.encrypted_values[2],
+ enc_note.encrypted_values[3],
+ ];
+
+ (prover_witnesses, public_inputs)
+}
+
+pub fn exec() -> (Vec, Vec) {
+ let proposer_limit = Fp::from(20);
+ let quorum = Fp::from(10);
+ let early_exec_quorum = Fp::from(10);
+ let approval_ratio_quot = Fp::from(67);
+ let approval_ratio_base = Fp::from(100);
+
+ let dao_notes_secret_key = SecretKey::random(&mut OsRng);
+ let dao_proposer_secret_key = SecretKey::random(&mut OsRng);
+ let dao_proposals_secret_key = SecretKey::random(&mut OsRng);
+ let dao_votes_secret_key = SecretKey::random(&mut OsRng);
+ let dao_exec_secret_key = SecretKey::random(&mut OsRng);
+ let dao_early_exec_secret_key = SecretKey::random(&mut OsRng);
+
+ let dao_notes_pub_key = PublicKey::from_secret(dao_notes_secret_key);
+ let dao_proposer_pub_key = PublicKey::from_secret(dao_proposer_secret_key);
+ let dao_proposals_pub_key = PublicKey::from_secret(dao_proposals_secret_key);
+ let dao_votes_pub_key = PublicKey::from_secret(dao_votes_secret_key);
+ let dao_exec_pub_key = PublicKey::from_secret(dao_exec_secret_key);
+ let dao_early_exec_pub_key = PublicKey::from_secret(dao_early_exec_secret_key);
+
+ let gov_token_id = Fp::random(&mut OsRng);
+ let bulla_blind = Fp::random(&mut OsRng);
+
+ let dao_bulla = poseidon_hash([
+ proposer_limit,
+ quorum,
+ early_exec_quorum,
+ approval_ratio_quot,
+ approval_ratio_base,
+ gov_token_id,
+ dao_notes_pub_key.x(),
+ dao_notes_pub_key.y(),
+ dao_proposer_pub_key.x(),
+ dao_proposer_pub_key.y(),
+ dao_proposals_pub_key.x(),
+ dao_proposals_pub_key.y(),
+ dao_votes_pub_key.x(),
+ dao_votes_pub_key.y(),
+ dao_exec_pub_key.x(),
+ dao_exec_pub_key.y(),
+ dao_early_exec_pub_key.x(),
+ dao_early_exec_pub_key.y(),
+ bulla_blind,
+ ]);
+
+ // Proposal info
+ let proposal_blind = BaseBlind::random(&mut OsRng);
+ let proposal_auth_calls_commit = Fp::random(&mut OsRng);
+ let proposal_creation_blockwindow = Fp::from(100000);
+ let proposal_duration_blockwindows = Fp::from(20);
+ let proposal_bulla = poseidon_hash([
+ proposal_auth_calls_commit,
+ proposal_creation_blockwindow,
+ proposal_duration_blockwindows,
+ Fp::ZERO,
+ dao_bulla,
+ proposal_blind.inner(),
+ ]);
+
+ // Vote Info
+ let yes_vote_value = 10000u64;
+ let yes_vote_blind = ScalarBlind::random(&mut OsRng);
+ let yes_vote_commit = pedersen_commitment_u64(yes_vote_value, yes_vote_blind);
+ let yes_vote_commit_coords = yes_vote_commit.to_affine().coordinates().unwrap();
+
+ let all_vote_value = 12000u64;
+ let all_vote_blind = ScalarBlind::random(&mut OsRng);
+ let all_vote_commit = pedersen_commitment_u64(all_vote_value, all_vote_blind);
+ let all_vote_commit_coords = all_vote_commit.to_affine().coordinates().unwrap();
+
+ let current_blockwindow = Fp::from(100075);
+
+ let sig_secret = SecretKey::random(&mut OsRng);
+ let sig_pubkey = PublicKey::from_secret(sig_secret);
+ let sig_pub_x = sig_pubkey.x();
+ let sig_pub_y = sig_pubkey.y();
+
+ let prover_witnesses = vec![
+ // Proposal params
+ Witness::Base(Value::known(proposal_auth_calls_commit)),
+ Witness::Base(Value::known(pallas::Base::from(proposal_creation_blockwindow))),
+ Witness::Base(Value::known(pallas::Base::from(proposal_duration_blockwindows))),
+ Witness::Base(Value::known(Fp::ZERO)),
+ Witness::Base(Value::known(proposal_blind.inner())),
+ // DAO params
+ Witness::Base(Value::known(proposer_limit)),
+ Witness::Base(Value::known(quorum)),
+ Witness::Base(Value::known(early_exec_quorum)),
+ Witness::Base(Value::known(approval_ratio_quot)),
+ Witness::Base(Value::known(approval_ratio_base)),
+ Witness::Base(Value::known(gov_token_id)),
+ Witness::Base(Value::known(dao_notes_pub_key.x())),
+ Witness::Base(Value::known(dao_notes_pub_key.y())),
+ Witness::Base(Value::known(dao_proposer_pub_key.x())),
+ Witness::Base(Value::known(dao_proposer_pub_key.y())),
+ Witness::Base(Value::known(dao_proposals_pub_key.x())),
+ Witness::Base(Value::known(dao_proposals_pub_key.y())),
+ Witness::Base(Value::known(dao_votes_pub_key.x())),
+ Witness::Base(Value::known(dao_votes_pub_key.y())),
+ Witness::Base(Value::known(dao_exec_secret_key.inner())),
+ Witness::Base(Value::known(dao_early_exec_pub_key.x())),
+ Witness::Base(Value::known(dao_early_exec_pub_key.y())),
+ Witness::Base(Value::known(bulla_blind)),
+ // Votes
+ Witness::Base(Value::known(Fp::from(yes_vote_value))),
+ Witness::Base(Value::known(Fp::from(all_vote_value))),
+ Witness::Scalar(Value::known(yes_vote_blind.inner())),
+ Witness::Scalar(Value::known(all_vote_blind.inner())),
+ // Time checks
+ Witness::Base(Value::known(current_blockwindow)),
+ // Signature secret
+ Witness::Base(Value::known(sig_secret.inner())),
+ ];
+
+ let public_inputs = vec![
+ proposal_bulla,
+ proposal_auth_calls_commit,
+ current_blockwindow,
+ *yes_vote_commit_coords.x(),
+ *yes_vote_commit_coords.y(),
+ *all_vote_commit_coords.x(),
+ *all_vote_commit_coords.y(),
+ sig_pub_x,
+ sig_pub_y,
+ ];
+
+ (prover_witnesses, public_inputs)
+}
+
+pub fn early_exec() -> (Vec, Vec) {
+ let proposer_limit = Fp::from(20);
+ let quorum = Fp::from(10);
+ let early_exec_quorum = Fp::from(10);
+ let approval_ratio_quot = Fp::from(67);
+ let approval_ratio_base = Fp::from(100);
+
+ let dao_notes_secret_key = SecretKey::random(&mut OsRng);
+ let dao_proposer_secret_key = SecretKey::random(&mut OsRng);
+ let dao_proposals_secret_key = SecretKey::random(&mut OsRng);
+ let dao_votes_secret_key = SecretKey::random(&mut OsRng);
+ let dao_exec_secret_key = SecretKey::random(&mut OsRng);
+ let dao_early_exec_secret_key = SecretKey::random(&mut OsRng);
+
+ let dao_notes_pub_key = PublicKey::from_secret(dao_notes_secret_key);
+ let dao_proposer_pub_key = PublicKey::from_secret(dao_proposer_secret_key);
+ let dao_proposals_pub_key = PublicKey::from_secret(dao_proposals_secret_key);
+ let dao_votes_pub_key = PublicKey::from_secret(dao_votes_secret_key);
+ let dao_exec_pub_key = PublicKey::from_secret(dao_exec_secret_key);
+ let dao_early_exec_pub_key = PublicKey::from_secret(dao_early_exec_secret_key);
+
+ let gov_token_id = Fp::random(&mut OsRng);
+ let bulla_blind = Fp::random(&mut OsRng);
+
+ let dao_bulla = poseidon_hash([
+ proposer_limit,
+ quorum,
+ early_exec_quorum,
+ approval_ratio_quot,
+ approval_ratio_base,
+ gov_token_id,
+ dao_notes_pub_key.x(),
+ dao_notes_pub_key.y(),
+ dao_proposer_pub_key.x(),
+ dao_proposer_pub_key.y(),
+ dao_proposals_pub_key.x(),
+ dao_proposals_pub_key.y(),
+ dao_votes_pub_key.x(),
+ dao_votes_pub_key.y(),
+ dao_exec_pub_key.x(),
+ dao_exec_pub_key.y(),
+ dao_early_exec_pub_key.x(),
+ dao_early_exec_pub_key.y(),
+ bulla_blind,
+ ]);
+
+ // Proposal info
+ let proposal_blind = BaseBlind::random(&mut OsRng);
+ let proposal_auth_calls_commit = Fp::random(&mut OsRng);
+ let proposal_creation_blockwindow = Fp::from(100000);
+ let proposal_duration_blockwindows = Fp::from(20);
+ let proposal_bulla = poseidon_hash([
+ proposal_auth_calls_commit,
+ proposal_creation_blockwindow,
+ proposal_duration_blockwindows,
+ Fp::ZERO,
+ dao_bulla,
+ proposal_blind.inner(),
+ ]);
+
+ // Vote Info
+ let yes_vote_value = 10000u64;
+ let yes_vote_blind = ScalarBlind::random(&mut OsRng);
+ let yes_vote_commit = pedersen_commitment_u64(yes_vote_value, yes_vote_blind);
+ let yes_vote_commit_coords = yes_vote_commit.to_affine().coordinates().unwrap();
+
+ let all_vote_value = 10000u64;
+ let all_vote_blind = ScalarBlind::random(&mut OsRng);
+ let all_vote_commit = pedersen_commitment_u64(all_vote_value, all_vote_blind);
+ let all_vote_commit_coords = all_vote_commit.to_affine().coordinates().unwrap();
+
+ let current_blockwindow = Fp::from(100015);
+
+ let sig_secret = SecretKey::random(&mut OsRng);
+ let sig_pubkey = PublicKey::from_secret(sig_secret);
+ let sig_pub_x = sig_pubkey.x();
+ let sig_pub_y = sig_pubkey.y();
+
+ let prover_witnesses = vec![
+ // Proposal params
+ Witness::Base(Value::known(proposal_auth_calls_commit)),
+ Witness::Base(Value::known(pallas::Base::from(proposal_creation_blockwindow))),
+ Witness::Base(Value::known(pallas::Base::from(proposal_duration_blockwindows))),
+ Witness::Base(Value::known(Fp::ZERO)),
+ Witness::Base(Value::known(proposal_blind.inner())),
+ // DAO params
+ Witness::Base(Value::known(proposer_limit)),
+ Witness::Base(Value::known(quorum)),
+ Witness::Base(Value::known(early_exec_quorum)),
+ Witness::Base(Value::known(approval_ratio_quot)),
+ Witness::Base(Value::known(approval_ratio_base)),
+ Witness::Base(Value::known(gov_token_id)),
+ Witness::Base(Value::known(dao_notes_pub_key.x())),
+ Witness::Base(Value::known(dao_notes_pub_key.y())),
+ Witness::Base(Value::known(dao_proposer_pub_key.x())),
+ Witness::Base(Value::known(dao_proposer_pub_key.y())),
+ Witness::Base(Value::known(dao_proposals_pub_key.x())),
+ Witness::Base(Value::known(dao_proposals_pub_key.y())),
+ Witness::Base(Value::known(dao_votes_pub_key.x())),
+ Witness::Base(Value::known(dao_votes_pub_key.y())),
+ Witness::Base(Value::known(dao_exec_secret_key.inner())),
+ Witness::Base(Value::known(dao_early_exec_secret_key.inner())),
+ Witness::Base(Value::known(bulla_blind)),
+ // Votes
+ Witness::Base(Value::known(Fp::from(yes_vote_value))),
+ Witness::Base(Value::known(Fp::from(all_vote_value))),
+ Witness::Scalar(Value::known(yes_vote_blind.inner())),
+ Witness::Scalar(Value::known(all_vote_blind.inner())),
+ // Time checks
+ Witness::Base(Value::known(current_blockwindow)),
+ // Signature secret
+ Witness::Base(Value::known(sig_secret.inner())),
+ ];
+
+ let public_inputs = vec![
+ proposal_bulla,
+ proposal_auth_calls_commit,
+ current_blockwindow,
+ *yes_vote_commit_coords.x(),
+ *yes_vote_commit_coords.y(),
+ *all_vote_commit_coords.x(),
+ *all_vote_commit_coords.y(),
+ sig_pub_x,
+ sig_pub_y,
+ ];
+
+ (prover_witnesses, public_inputs)
+}
+
+pub fn auth_money_transfer() -> (Vec, Vec) {
+ let proposer_limit = Fp::from(20);
+ let quorum = Fp::from(10);
+ let early_exec_quorum = Fp::from(10);
+ let approval_ratio_quot = Fp::from(67);
+ let approval_ratio_base = Fp::from(100);
+
+ let dao_notes_secret_key = SecretKey::random(&mut OsRng);
+ let dao_proposer_secret_key = SecretKey::random(&mut OsRng);
+ let dao_proposals_secret_key = SecretKey::random(&mut OsRng);
+ let dao_votes_secret_key = SecretKey::random(&mut OsRng);
+ let dao_exec_secret_key = SecretKey::random(&mut OsRng);
+ let dao_early_exec_secret_key = SecretKey::random(&mut OsRng);
+
+ let dao_notes_pub_key = PublicKey::from_secret(dao_notes_secret_key);
+ let dao_proposer_pub_key = PublicKey::from_secret(dao_proposer_secret_key);
+ let dao_proposals_pub_key = PublicKey::from_secret(dao_proposals_secret_key);
+ let dao_votes_pub_key = PublicKey::from_secret(dao_votes_secret_key);
+ let dao_exec_pub_key = PublicKey::from_secret(dao_exec_secret_key);
+ let dao_early_exec_pub_key = PublicKey::from_secret(dao_early_exec_secret_key);
+
+ let gov_token_id = Fp::random(&mut OsRng);
+ let bulla_blind = Fp::random(&mut OsRng);
+
+ let dao_bulla = poseidon_hash([
+ proposer_limit,
+ quorum,
+ early_exec_quorum,
+ approval_ratio_quot,
+ approval_ratio_base,
+ gov_token_id,
+ dao_notes_pub_key.x(),
+ dao_notes_pub_key.y(),
+ dao_proposer_pub_key.x(),
+ dao_proposer_pub_key.y(),
+ dao_proposals_pub_key.x(),
+ dao_proposals_pub_key.y(),
+ dao_votes_pub_key.x(),
+ dao_votes_pub_key.y(),
+ dao_exec_pub_key.x(),
+ dao_exec_pub_key.y(),
+ dao_early_exec_pub_key.x(),
+ dao_early_exec_pub_key.y(),
+ bulla_blind,
+ ]);
+
+ // Proposal info
+ let proposal_blind = BaseBlind::random(&mut OsRng);
+ let proposal_auth_calls_commit = Fp::random(&mut OsRng);
+ let proposal_creation_blockwindow = Fp::from(100000);
+ let proposal_duration_blockwindows = Fp::from(20);
+ let proposal_bulla = poseidon_hash([
+ proposal_auth_calls_commit,
+ proposal_creation_blockwindow,
+ proposal_duration_blockwindows,
+ Fp::ZERO,
+ dao_bulla,
+ proposal_blind.inner(),
+ ]);
+
+ // Coin Info
+ let coin_token_id = Fp::random(&mut OsRng);
+ let coin_blind = BaseBlind::random(&mut OsRng);
+ let dao_spend_hook = Fp::from(3); //Dao::Exec
+
+ let dao_change_value = pallas::Base::from(23u64);
+ let dao_change_coin = poseidon_hash([
+ dao_notes_pub_key.x(),
+ dao_notes_pub_key.y(),
+ dao_change_value,
+ coin_token_id,
+ dao_spend_hook,
+ dao_bulla,
+ coin_blind.inner(),
+ ]);
+
+ let ephem_secret = SecretKey::random(&mut OsRng);
+ let change_ephem_pubkey = PublicKey::from_secret(ephem_secret);
+ let (ephem_x, ephem_y) = change_ephem_pubkey.xy();
+
+ let note = [dao_change_value, coin_token_id, coin_blind.inner()];
+
+ let dao_change_attrs =
+ ElGamalEncryptedNote::encrypt_unsafe(note, &ephem_secret, &dao_notes_pub_key).unwrap();
+
+ let input_user_data_blind = BaseBlind::random(&mut OsRng);
+ let input_user_data_enc = poseidon_hash([dao_bulla, input_user_data_blind.inner()]);
+
+ let prover_witnesses = vec![
+ // proposal params
+ Witness::Base(Value::known(proposal_auth_calls_commit)),
+ Witness::Base(Value::known(proposal_creation_blockwindow)),
+ Witness::Base(Value::known(pallas::Base::from(proposal_duration_blockwindows))),
+ Witness::Base(Value::known(Fp::ZERO)),
+ Witness::Base(Value::known(proposal_blind.inner())),
+ // DAO params
+ Witness::Base(Value::known(proposer_limit)),
+ Witness::Base(Value::known(quorum)),
+ Witness::Base(Value::known(early_exec_quorum)),
+ Witness::Base(Value::known(approval_ratio_quot)),
+ Witness::Base(Value::known(approval_ratio_base)),
+ Witness::Base(Value::known(gov_token_id)),
+ Witness::EcNiPoint(Value::known(dao_notes_pub_key.inner())),
+ Witness::Base(Value::known(dao_proposer_pub_key.x())),
+ Witness::Base(Value::known(dao_proposer_pub_key.y())),
+ Witness::Base(Value::known(dao_proposals_pub_key.x())),
+ Witness::Base(Value::known(dao_proposals_pub_key.y())),
+ Witness::Base(Value::known(dao_votes_pub_key.x())),
+ Witness::Base(Value::known(dao_votes_pub_key.y())),
+ Witness::Base(Value::known(dao_exec_pub_key.x())),
+ Witness::Base(Value::known(dao_exec_pub_key.y())),
+ Witness::Base(Value::known(dao_early_exec_pub_key.x())),
+ Witness::Base(Value::known(dao_early_exec_pub_key.y())),
+ Witness::Base(Value::known(bulla_blind)),
+ // Dao input user data blind
+ Witness::Base(Value::known(input_user_data_blind.inner())),
+ // Dao output coin attrs
+ Witness::Base(Value::known(dao_change_value)),
+ Witness::Base(Value::known(coin_token_id)),
+ Witness::Base(Value::known(coin_blind.inner())),
+ // DAO::exec() func ID
+ Witness::Base(Value::known(dao_spend_hook)),
+ // Encrypted change DAO output
+ Witness::Base(Value::known(ephem_secret.inner())),
+ ];
+
+ let public_inputs = vec![
+ proposal_bulla,
+ input_user_data_enc,
+ dao_change_coin,
+ dao_spend_hook,
+ proposal_auth_calls_commit,
+ ephem_x,
+ ephem_y,
+ dao_change_attrs.encrypted_values[0],
+ dao_change_attrs.encrypted_values[1],
+ dao_change_attrs.encrypted_values[2],
+ ];
+
+ (prover_witnesses, public_inputs)
+}
+
+pub fn auth_money_transfer_enc_coin() -> (Vec, Vec) {
+ // Coin Info
+ let coin_secret = SecretKey::random(&mut OsRng);
+ let coin_pub_key = PublicKey::from_secret(coin_secret);
+ let coin_token_id = Fp::random(&mut OsRng);
+ let coin_blind = BaseBlind::random(&mut OsRng);
+ let coin_spend_hook = Fp::ZERO;
+ let coin_user_data = Fp::ZERO;
+
+ let coin_value = pallas::Base::from(23u64);
+ let coin = poseidon_hash([
+ coin_pub_key.x(),
+ coin_pub_key.y(),
+ coin_value,
+ coin_token_id,
+ coin_spend_hook,
+ coin_user_data,
+ coin_blind.inner(),
+ ]);
+
+ let ephem_secret = SecretKey::random(&mut OsRng);
+ let change_ephem_pubkey = PublicKey::from_secret(ephem_secret);
+ let (ephem_x, ephem_y) = change_ephem_pubkey.xy();
+
+ let note = [coin_value, coin_token_id, coin_spend_hook, coin_user_data, coin_blind.inner()];
+ let enc_note =
+ ElGamalEncryptedNote::encrypt_unsafe(note, &ephem_secret, &coin_pub_key).unwrap();
+
+ let prover_witnesses = vec![
+ Witness::EcNiPoint(Value::known(coin_pub_key.inner())),
+ Witness::Base(Value::known(coin_value)),
+ Witness::Base(Value::known(coin_token_id)),
+ Witness::Base(Value::known(coin_spend_hook)),
+ Witness::Base(Value::known(coin_user_data)),
+ Witness::Base(Value::known(coin_blind.inner())),
+ Witness::Base(Value::known(ephem_secret.inner())),
+ ];
+
+ let public_inputs = vec![
+ coin,
+ ephem_x,
+ ephem_y,
+ enc_note.encrypted_values[0],
+ enc_note.encrypted_values[1],
+ enc_note.encrypted_values[2],
+ enc_note.encrypted_values[3],
+ enc_note.encrypted_values[4],
+ ];
+
+ (prover_witnesses, public_inputs)
+}
diff --git a/script/research/zkvm-metering/generator/src/dao/proof/dao_auth_money_transfer.zk b/script/research/zkvm-metering/generator/src/dao/proof/dao_auth_money_transfer.zk
new file mode 120000
index 000000000..c1711fc7e
--- /dev/null
+++ b/script/research/zkvm-metering/generator/src/dao/proof/dao_auth_money_transfer.zk
@@ -0,0 +1 @@
+../../../../../../../src/contract/dao/proof/auth-money-transfer.zk
\ No newline at end of file
diff --git a/script/research/zkvm-metering/generator/src/dao/proof/dao_auth_money_transfer_enc_coin.zk b/script/research/zkvm-metering/generator/src/dao/proof/dao_auth_money_transfer_enc_coin.zk
new file mode 120000
index 000000000..d250742d1
--- /dev/null
+++ b/script/research/zkvm-metering/generator/src/dao/proof/dao_auth_money_transfer_enc_coin.zk
@@ -0,0 +1 @@
+../../../../../../../src/contract/dao/proof/auth-money-transfer-enc-coin.zk
\ No newline at end of file
diff --git a/script/research/zkvm-metering/generator/src/dao/proof/dao_early_exec.zk b/script/research/zkvm-metering/generator/src/dao/proof/dao_early_exec.zk
new file mode 120000
index 000000000..83618e564
--- /dev/null
+++ b/script/research/zkvm-metering/generator/src/dao/proof/dao_early_exec.zk
@@ -0,0 +1 @@
+../../../../../../../src/contract/dao/proof/early-exec.zk
\ No newline at end of file
diff --git a/script/research/zkvm-metering/generator/src/dao/proof/dao_exec.zk b/script/research/zkvm-metering/generator/src/dao/proof/dao_exec.zk
new file mode 120000
index 000000000..d9e083017
--- /dev/null
+++ b/script/research/zkvm-metering/generator/src/dao/proof/dao_exec.zk
@@ -0,0 +1 @@
+../../../../../../../src/contract/dao/proof/exec.zk
\ No newline at end of file
diff --git a/script/research/zkvm-metering/generator/src/dao/proof/dao_mint.zk b/script/research/zkvm-metering/generator/src/dao/proof/dao_mint.zk
new file mode 120000
index 000000000..37838739c
--- /dev/null
+++ b/script/research/zkvm-metering/generator/src/dao/proof/dao_mint.zk
@@ -0,0 +1 @@
+../../../../../../../src/contract/dao/proof/mint.zk
\ No newline at end of file
diff --git a/script/research/zkvm-metering/generator/src/dao/proof/dao_propose_input.zk b/script/research/zkvm-metering/generator/src/dao/proof/dao_propose_input.zk
new file mode 120000
index 000000000..f1e30e2cb
--- /dev/null
+++ b/script/research/zkvm-metering/generator/src/dao/proof/dao_propose_input.zk
@@ -0,0 +1 @@
+../../../../../../../src/contract/dao/proof/propose-input.zk
\ No newline at end of file
diff --git a/script/research/zkvm-metering/generator/src/dao/proof/dao_propose_main.zk b/script/research/zkvm-metering/generator/src/dao/proof/dao_propose_main.zk
new file mode 120000
index 000000000..49ffea844
--- /dev/null
+++ b/script/research/zkvm-metering/generator/src/dao/proof/dao_propose_main.zk
@@ -0,0 +1 @@
+../../../../../../../src/contract/dao/proof/propose-main.zk
\ No newline at end of file
diff --git a/script/research/zkvm-metering/generator/src/dao/proof/dao_vote_input.zk b/script/research/zkvm-metering/generator/src/dao/proof/dao_vote_input.zk
new file mode 120000
index 000000000..d306ed406
--- /dev/null
+++ b/script/research/zkvm-metering/generator/src/dao/proof/dao_vote_input.zk
@@ -0,0 +1 @@
+../../../../../../../src/contract/dao/proof/vote-input.zk
\ No newline at end of file
diff --git a/script/research/zkvm-metering/generator/src/dao/proof/dao_vote_main.zk b/script/research/zkvm-metering/generator/src/dao/proof/dao_vote_main.zk
new file mode 120000
index 000000000..875d2dc76
--- /dev/null
+++ b/script/research/zkvm-metering/generator/src/dao/proof/dao_vote_main.zk
@@ -0,0 +1 @@
+../../../../../../../src/contract/dao/proof/vote-main.zk
\ No newline at end of file
diff --git a/script/research/zkvm-metering/generator/src/main.rs b/script/research/zkvm-metering/generator/src/main.rs
index 80f8b2f9b..aff0eddb2 100644
--- a/script/research/zkvm-metering/generator/src/main.rs
+++ b/script/research/zkvm-metering/generator/src/main.rs
@@ -31,6 +31,11 @@ use darkfi_serial::serialize;
use halo2_proofs::dev::CircuitCost;
use rand::rngs::OsRng;
+/// Dao contract zk proofs witness and public input generator.
+mod dao;
+
+/// Money contract zk proofs witness and public input generator.
+mod money;
/// Opcode zk proofs witness and public input generator.
mod opcodes;
@@ -135,6 +140,20 @@ fn retrieve_proof_inputs(name: &str) -> (Vec, Vec) {
"zero_cond" => opcodes::zero_cond(),
"range_check" => opcodes::range_check(),
"debug" => opcodes::debug(),
+ "money_mint_v1" => money::mint_v1(),
+ "money_burn_v1" => money::burn_v1(),
+ "money_fee_v1" => money::fee_v1(),
+ "money_token_mint_v1" => money::token_mint_v1(),
+ "money_auth_token_mint_v1" => money::auth_token_mint_v1(),
+ "dao_mint" => dao::mint(),
+ "dao_propose_input" => dao::propose_input(),
+ "dao_propose_main" => dao::propose_main(),
+ "dao_vote_input" => dao::vote_input(),
+ "dao_vote_main" => dao::vote_main(),
+ "dao_exec" => dao::exec(),
+ "dao_early_exec" => dao::early_exec(),
+ "dao_auth_money_transfer" => dao::auth_money_transfer(),
+ "dao_auth_money_transfer_enc_coin" => dao::auth_money_transfer_enc_coin(),
_ => panic!("unsupported Zk script"),
}
}
diff --git a/script/research/zkvm-metering/generator/src/money/mod.rs b/script/research/zkvm-metering/generator/src/money/mod.rs
new file mode 100644
index 000000000..99dbc2b4f
--- /dev/null
+++ b/script/research/zkvm-metering/generator/src/money/mod.rs
@@ -0,0 +1,342 @@
+/* This file is part of DarkFi (https://dark.fi)
+ *
+ * Copyright (C) 2020-2026 Dyne.org foundation
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+use darkfi::zk::{Witness, halo2::Field};
+use darkfi_sdk::{
+ crypto::{
+ BaseBlind, FuncRef, MONEY_CONTRACT_ID, MerkleNode, MerkleTree, PublicKey, ScalarBlind,
+ SecretKey,
+ pasta_prelude::{Curve, CurveAffine},
+ pedersen_commitment_u64,
+ util::poseidon_hash,
+ },
+ pasta::{Fp, pallas, pallas::Base},
+};
+use halo2_proofs::circuit::Value;
+use rand::rngs::OsRng;
+
+pub fn mint_v1() -> (Vec, Vec) {
+ let secret_key = SecretKey::random(&mut OsRng);
+ let pubkey = PublicKey::from_secret(secret_key);
+ let coin_pub_x = pubkey.x();
+ let coin_pub_y = pubkey.y();
+ let coin_value = 23u64;
+ let coin_token_id = Fp::random(&mut OsRng);
+ let coin_spend_hook = Fp::from(0);
+ let coin_user_data = Fp::from(0);
+ let coin_blind = BaseBlind::random(&mut OsRng);
+ let value_blind = ScalarBlind::random(&mut OsRng);
+ let coin_token_id_blind = BaseBlind::random(&mut OsRng);
+
+ let coin = poseidon_hash([
+ coin_pub_x,
+ coin_pub_y,
+ Fp::from(coin_value),
+ coin_token_id,
+ coin_spend_hook,
+ coin_user_data,
+ coin_blind.inner(),
+ ]);
+ let value_commit = (pedersen_commitment_u64(coin_value, value_blind)).to_affine();
+ let value_commit_x = *value_commit.coordinates().unwrap().x();
+ let value_commit_y = *value_commit.coordinates().unwrap().y();
+ let token_commit = poseidon_hash([coin_token_id, coin_token_id_blind.inner()]);
+
+ let prover_witnesses = vec![
+ Witness::Base(Value::known(coin_pub_x)),
+ Witness::Base(Value::known(coin_pub_y)),
+ Witness::Base(Value::known(pallas::Base::from(coin_value))),
+ Witness::Base(Value::known(coin_token_id)),
+ Witness::Base(Value::known(coin_spend_hook)),
+ Witness::Base(Value::known(coin_user_data)),
+ Witness::Base(Value::known(coin_blind.inner())),
+ Witness::Scalar(Value::known(value_blind.inner())),
+ Witness::Base(Value::known(coin_token_id_blind.inner())),
+ ];
+
+ let public_inputs = vec![coin, value_commit_x, value_commit_y, token_commit];
+
+ (prover_witnesses, public_inputs)
+}
+
+pub fn burn_v1() -> (Vec, Vec) {
+ let coin_secret = SecretKey::random(&mut OsRng);
+ let coin_pubkey = PublicKey::from_secret(coin_secret);
+ let coin_pub_x = coin_pubkey.x();
+ let coin_pub_y = coin_pubkey.y();
+
+ let sig_secret = SecretKey::random(&mut OsRng);
+ let sig_pubkey = PublicKey::from_secret(sig_secret);
+ let sig_pub_x = sig_pubkey.x();
+ let sig_pub_y = sig_pubkey.y();
+
+ let coin_value = 23u64;
+ let coin_token_id = Fp::random(&mut OsRng);
+ let coin_spend_hook = Fp::from(0);
+ let coin_user_data = Fp::from(0);
+ let coin_blind = BaseBlind::random(&mut OsRng);
+ let value_blind = ScalarBlind::random(&mut OsRng);
+ let coin_token_id_blind = BaseBlind::random(&mut OsRng);
+ let user_data_blind = BaseBlind::random(&mut OsRng);
+
+ let my_coin = poseidon_hash([
+ coin_pub_x,
+ coin_pub_y,
+ Fp::from(coin_value),
+ coin_token_id,
+ coin_spend_hook,
+ coin_user_data,
+ coin_blind.inner(),
+ ]);
+
+ let mut tree = MerkleTree::new(u32::MAX as usize);
+ let coin1 = MerkleNode::from(Fp::random(&mut OsRng));
+ let coin2 = MerkleNode::from(Fp::random(&mut OsRng));
+ tree.append(coin1);
+ tree.mark();
+ tree.append(MerkleNode::from(my_coin));
+ let leaf_position = tree.mark().unwrap();
+ tree.append(coin2);
+
+ let root = tree.root(0).unwrap().inner();
+ let merkle_path = tree.witness(leaf_position, 0).unwrap();
+
+ let nullifier = poseidon_hash([coin_secret.inner(), my_coin]);
+ let user_data_enc = poseidon_hash([coin_user_data, user_data_blind.inner()]);
+ let value_commit = pedersen_commitment_u64(coin_value, value_blind).to_affine();
+ let value_commit_x = *value_commit.coordinates().unwrap().x();
+ let value_commit_y = *value_commit.coordinates().unwrap().y();
+ let token_id_commit = poseidon_hash([coin_token_id, coin_token_id_blind.inner()]);
+
+ let prover_witnesses = vec![
+ Witness::Base(Value::known(coin_secret.inner())),
+ Witness::Base(Value::known(Fp::from(coin_value))),
+ Witness::Base(Value::known(coin_token_id)),
+ Witness::Base(Value::known(coin_spend_hook)),
+ Witness::Base(Value::known(coin_user_data)),
+ Witness::Base(Value::known(coin_blind.inner())),
+ Witness::Scalar(Value::known(value_blind.inner())),
+ Witness::Base(Value::known(coin_token_id_blind.inner())),
+ Witness::Base(Value::known(user_data_blind.inner())),
+ Witness::Uint32(Value::known(u64::from(leaf_position).try_into().unwrap())),
+ Witness::MerklePath(Value::known(merkle_path.clone().try_into().unwrap())),
+ Witness::Base(Value::known(sig_secret.inner())),
+ ];
+
+ let public_inputs = vec![
+ nullifier,
+ value_commit_x,
+ value_commit_y,
+ token_id_commit,
+ root,
+ user_data_enc,
+ coin_spend_hook,
+ sig_pub_x,
+ sig_pub_y,
+ ];
+
+ (prover_witnesses, public_inputs)
+}
+
+pub fn fee_v1() -> (Vec, Vec) {
+ let token_id = Fp::random(&mut OsRng);
+ let token_id_blind = BaseBlind::random(&mut OsRng);
+ let coin_secret = SecretKey::random(&mut OsRng);
+ let coin_pubkey = PublicKey::from_secret(coin_secret);
+ let coin_pub_x = coin_pubkey.x();
+ let coin_pub_y = coin_pubkey.y();
+ // Input Coin Info
+ let input_coin_value = 23u64;
+ let input_coin_spend_hook = Fp::from(0);
+ let input_coin_user_data = Fp::from(0);
+ let input_coin_blind = BaseBlind::random(&mut OsRng);
+ let input_value_blind = ScalarBlind::random(&mut OsRng);
+ let input_user_data_blind = BaseBlind::random(&mut OsRng);
+
+ let input_coin = poseidon_hash([
+ coin_pub_x,
+ coin_pub_y,
+ Fp::from(input_coin_value),
+ token_id,
+ input_coin_spend_hook,
+ input_coin_user_data,
+ input_coin_blind.inner(),
+ ]);
+
+ let input_coin_nullifier = poseidon_hash([coin_secret.inner(), input_coin]);
+ let input_coin_user_data_enc =
+ poseidon_hash([input_coin_user_data, input_user_data_blind.inner()]);
+ let input_coin_value_commit =
+ (pedersen_commitment_u64(input_coin_value, input_value_blind)).to_affine();
+ let input_coin_value_commit_x = *input_coin_value_commit.coordinates().unwrap().x();
+ let input_coin_value_commit_y = *input_coin_value_commit.coordinates().unwrap().y();
+
+ let sig_secret = SecretKey::random(&mut OsRng);
+ let sig_pubkey = PublicKey::from_secret(sig_secret);
+ let sig_pub_x = sig_pubkey.x();
+ let sig_pub_y = sig_pubkey.y();
+
+ let mut tree = MerkleTree::new(u32::MAX as usize);
+ let coin1 = MerkleNode::from(Fp::random(&mut OsRng));
+ let coin2 = MerkleNode::from(Fp::random(&mut OsRng));
+ tree.append(coin1);
+ tree.mark();
+ tree.append(MerkleNode::from(input_coin));
+ let input_coin_leaf_position = tree.mark().unwrap();
+ tree.append(coin2);
+
+ let root = tree.root(0).unwrap().inner();
+ let input_coin_merkle_path = tree.witness(input_coin_leaf_position, 0).unwrap();
+
+ // Output Coin Info
+ let output_coin_value = 22u64;
+ let output_coin_spend_hook = Fp::from(0);
+ let output_coin_user_data = Fp::from(0);
+ let output_coin_blind = BaseBlind::random(&mut OsRng);
+ let output_value_blind = ScalarBlind::random(&mut OsRng);
+
+ let output_coin = poseidon_hash([
+ coin_pub_x,
+ coin_pub_y,
+ Fp::from(output_coin_value),
+ token_id,
+ output_coin_spend_hook,
+ output_coin_user_data,
+ output_coin_blind.inner(),
+ ]);
+
+ let output_coin_value_commit =
+ (pedersen_commitment_u64(output_coin_value, output_value_blind)).to_affine();
+ let output_coin_value_commit_x = *output_coin_value_commit.coordinates().unwrap().x();
+ let output_coin_value_commit_y = *output_coin_value_commit.coordinates().unwrap().y();
+ let token_id_commit = poseidon_hash([token_id, token_id_blind.inner()]);
+
+ let prover_witnesses = vec![
+ Witness::Base(Value::known(coin_secret.inner())),
+ Witness::Uint32(Value::known(u64::from(input_coin_leaf_position).try_into().unwrap())),
+ Witness::MerklePath(Value::known(input_coin_merkle_path.clone().try_into().unwrap())),
+ Witness::Base(Value::known(sig_secret.inner())),
+ Witness::Base(Value::known(pallas::Base::from(input_coin_value))),
+ Witness::Scalar(Value::known(input_value_blind.inner())),
+ Witness::Base(Value::known(input_coin_spend_hook)),
+ Witness::Base(Value::known(input_coin_user_data)),
+ Witness::Base(Value::known(input_coin_blind.inner())),
+ Witness::Base(Value::known(input_user_data_blind.inner())),
+ Witness::Base(Value::known(pallas::Base::from(output_coin_value))),
+ Witness::Base(Value::known(output_coin_spend_hook)),
+ Witness::Base(Value::known(output_coin_user_data)),
+ Witness::Scalar(Value::known(output_value_blind.inner())),
+ Witness::Base(Value::known(output_coin_blind.inner())),
+ Witness::Base(Value::known(token_id)),
+ Witness::Base(Value::known(token_id_blind.inner())),
+ ];
+
+ let public_inputs = vec![
+ input_coin_nullifier,
+ input_coin_value_commit_x,
+ input_coin_value_commit_y,
+ token_id_commit,
+ root,
+ input_coin_user_data_enc,
+ sig_pub_x,
+ sig_pub_y,
+ output_coin,
+ output_coin_value_commit_x,
+ output_coin_value_commit_y,
+ ];
+
+ (prover_witnesses, public_inputs)
+}
+
+pub fn token_mint_v1() -> (Vec, Vec) {
+ let secret_key = SecretKey::random(&mut OsRng);
+ let pubkey = PublicKey::from_secret(secret_key);
+ let coin_pub_x = pubkey.x();
+ let coin_pub_y = pubkey.y();
+ let coin_value = 23u64;
+ let coin_spend_hook = Fp::from(0);
+ let coin_user_data = Fp::from(0);
+ let coin_blind = BaseBlind::random(&mut OsRng);
+
+ // Token Attributes
+ let token_auth_parent = FuncRef {
+ contract_id: *MONEY_CONTRACT_ID,
+ func_code: 0x05, //MoneyFunction::AuthTokenMintV1 as u8,
+ }
+ .to_func_id();
+ let mint_authority = SecretKey::random(&mut OsRng);
+ let (mint_auth_x, mint_auth_y) = PublicKey::from_secret(mint_authority).xy();
+ let token_user_data = poseidon_hash([mint_auth_x, mint_auth_y]);
+ let token_id_blind = BaseBlind::random(&mut OsRng);
+ let token_id =
+ poseidon_hash([token_auth_parent.inner(), token_user_data, token_id_blind.inner()]);
+
+ let coin = poseidon_hash([
+ coin_pub_x,
+ coin_pub_y,
+ Fp::from(coin_value),
+ token_id,
+ coin_spend_hook,
+ coin_user_data,
+ coin_blind.inner(),
+ ]);
+
+ let prover_witnesses = vec![
+ // Coin attributes
+ Witness::Base(Value::known(coin_pub_x)),
+ Witness::Base(Value::known(coin_pub_y)),
+ Witness::Base(Value::known(pallas::Base::from(coin_value))),
+ Witness::Base(Value::known(coin_spend_hook)),
+ Witness::Base(Value::known(coin_user_data)),
+ Witness::Base(Value::known(coin_blind.inner())),
+ // Token attributes
+ Witness::Base(Value::known(token_auth_parent.inner())),
+ Witness::Base(Value::known(token_user_data)),
+ Witness::Base(Value::known(token_id_blind.inner())),
+ ];
+
+ let public_inputs = vec![token_auth_parent.inner(), coin];
+
+ (prover_witnesses, public_inputs)
+}
+
+pub fn auth_token_mint_v1() -> (Vec, Vec) {
+ let token_auth_parent = FuncRef {
+ contract_id: *MONEY_CONTRACT_ID,
+ func_code: 0x05, //MoneyFunction::AuthTokenMintV1 as u8,
+ }
+ .to_func_id();
+ let mint_authority = SecretKey::random(&mut OsRng);
+ let (mint_pub_x, mint_pub_y) = PublicKey::from_secret(mint_authority).xy();
+ let token_user_data = poseidon_hash([mint_pub_x, mint_pub_y]);
+ let token_id_blind = BaseBlind::random(&mut OsRng);
+ let token_id =
+ poseidon_hash([token_auth_parent.inner(), token_user_data, token_id_blind.inner()]);
+
+ let prover_witnesses = vec![
+ // Token attributes
+ Witness::Base(Value::known(token_auth_parent.inner())),
+ Witness::Base(Value::known(token_id_blind.inner())),
+ // Secret key used by the mint authority
+ Witness::Base(Value::known(mint_authority.inner())),
+ ];
+
+ let public_inputs = vec![mint_pub_x, mint_pub_y, token_id];
+
+ (prover_witnesses, public_inputs)
+}
diff --git a/script/research/zkvm-metering/generator/src/money/proof/money_auth_token_mint_v1.zk b/script/research/zkvm-metering/generator/src/money/proof/money_auth_token_mint_v1.zk
new file mode 120000
index 000000000..fc88de680
--- /dev/null
+++ b/script/research/zkvm-metering/generator/src/money/proof/money_auth_token_mint_v1.zk
@@ -0,0 +1 @@
+../../../../../../../src/contract/money/proof/auth_token_mint_v1.zk
\ No newline at end of file
diff --git a/script/research/zkvm-metering/generator/src/money/proof/money_burn_v1.zk b/script/research/zkvm-metering/generator/src/money/proof/money_burn_v1.zk
new file mode 120000
index 000000000..6676bf81f
--- /dev/null
+++ b/script/research/zkvm-metering/generator/src/money/proof/money_burn_v1.zk
@@ -0,0 +1 @@
+../../../../../../../src/contract/money/proof/burn_v1.zk
\ No newline at end of file
diff --git a/script/research/zkvm-metering/generator/src/money/proof/money_fee_v1.zk b/script/research/zkvm-metering/generator/src/money/proof/money_fee_v1.zk
new file mode 120000
index 000000000..f20407285
--- /dev/null
+++ b/script/research/zkvm-metering/generator/src/money/proof/money_fee_v1.zk
@@ -0,0 +1 @@
+../../../../../../../src/contract/money/proof/fee_v1.zk
\ No newline at end of file
diff --git a/script/research/zkvm-metering/generator/src/money/proof/money_mint_v1.zk b/script/research/zkvm-metering/generator/src/money/proof/money_mint_v1.zk
new file mode 120000
index 000000000..881ed6d25
--- /dev/null
+++ b/script/research/zkvm-metering/generator/src/money/proof/money_mint_v1.zk
@@ -0,0 +1 @@
+../../../../../../../src/contract/money/proof/mint_v1.zk
\ No newline at end of file
diff --git a/script/research/zkvm-metering/generator/src/money/proof/money_token_mint_v1.zk b/script/research/zkvm-metering/generator/src/money/proof/money_token_mint_v1.zk
new file mode 120000
index 000000000..a6a7c7fe0
--- /dev/null
+++ b/script/research/zkvm-metering/generator/src/money/proof/money_token_mint_v1.zk
@@ -0,0 +1 @@
+../../../../../../../src/contract/money/proof/token_mint_v1.zk
\ No newline at end of file