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