Forráskód Böngészése

basic structure for dao-propose-main.zk working

narodnik 4 éve
szülő
commit
78766ef671

+ 44 - 8
bin/daod/proof/dao-propose-main.zk

@@ -1,20 +1,29 @@
 constant "DaoProposeMain" {
+	EcFixedPointShort VALUE_COMMIT_VALUE,
+	EcFixedPoint VALUE_COMMIT_RANDOM,
 }
 
 contract "DaoProposeMain" {
+    # Proposers total number of gov tokens
+    Base total_funds,
+    Scalar total_funds_blind,
+
+    # Check the inputs and this proof are for the same token
+    Base gov_token_blind,
+
     # proposal params
-    #Base proposal_x,
-    #Base proposal_y,
-    #Base proposal_amount,
-    #Base proposal_serial,
-    #Base proposal_token_id,
-    #Base proposal_blind,
+    Base proposal_x,
+    Base proposal_y,
+    Base proposal_amount,
+    Base proposal_serial,
+    Base proposal_token_id,
+    Base proposal_blind,
 
     # DAO params
     Base dao_proposer_limit,
     Base dao_quorum,
     Base dao_approval_ratio,
-    Base gdrk_token_id,
+    Base gov_token_id,
     Base dao_public_x,
     Base dao_public_y,
     Base dao_bulla_blind,
@@ -24,11 +33,14 @@ contract "DaoProposeMain" {
 }
 
 circuit "DaoProposeMain" {
+    token_commit = poseidon_hash(gov_token_id, gov_token_blind);
+	constrain_instance(token_commit);
+
     dao_bulla = poseidon_hash(
         dao_proposer_limit,
         dao_quorum,
         dao_approval_ratio,
-        gdrk_token_id,
+        gov_token_id,
         dao_public_x,
         dao_public_y,
         dao_bulla_blind,
@@ -38,5 +50,29 @@ circuit "DaoProposeMain" {
 	dao_root = calculate_merkle_root(dao_leaf_pos, dao_path, dao_bulla);
 	constrain_instance(dao_root);
     # Proves this DAO is valid
+
+    # Rangeproof check for proposal amount
+    # TODO: waiting on this opcode in zkas
+    #
+    #     greater_than_zero(amount)
+    #
+    # Use this temporary workaround. ec_mul_short() does an internal rangeproof
+    rangeproof = ec_mul_short(proposal_amount, VALUE_COMMIT_VALUE);
+
+    # TODO: check total_funds >= proposer_limit
+    #
+    #     greater_than_or_equal(total_funds, proposer_limit)
+    #
+
+	# Pedersen commitment for coin's value
+	vcv = ec_mul_short(total_funds, VALUE_COMMIT_VALUE);
+	vcr = ec_mul(total_funds_blind, VALUE_COMMIT_RANDOM);
+	total_funds_commit = ec_add(vcv, vcr);
+	# Since total_funds_commit is a curve point, we fetch its coordinates
+	# and constrain them:
+	total_funds_commit_x = ec_get_x(total_funds_commit);
+	total_funds_commit_y = ec_get_y(total_funds_commit);
+	constrain_instance(total_funds_commit_x);
+	constrain_instance(total_funds_commit_y);
 }
 

+ 7 - 1
bin/daod/src/dao_contract/propose/validate.rs

@@ -22,11 +22,17 @@ type Result<T> = std::result::Result<T, Error>;
 
 pub struct CallData {
     pub dao_merkle_root: MerkleNode,
+    pub token_commit: pallas::Base,
+    // TODO: compute from sum of input commits
+    pub total_funds_commit: pallas::Point,
 }
 
 impl CallDataBase for CallData {
     fn zk_public_values(&self) -> Vec<Vec<DrkCircuitField>> {
-        vec![vec![self.dao_merkle_root.0]]
+        let total_funds_coords = self.total_funds_commit.to_affine().coordinates().unwrap();
+        let total_funds_x = *total_funds_coords.x();
+        let total_funds_y = *total_funds_coords.y();
+        vec![vec![self.token_commit, self.dao_merkle_root.0, total_funds_x, total_funds_y]]
     }
 
     fn zk_proof_addrs(&self) -> Vec<String> {

+ 27 - 9
bin/daod/src/dao_contract/propose/wallet.rs

@@ -18,6 +18,7 @@ use darkfi::{
             DrkCircuitField, DrkCoinBlind, DrkSerial, DrkSpendHook, DrkTokenId, DrkUserData,
             DrkUserDataBlind, DrkValueBlind,
         },
+        util::{pedersen_commitment_base, pedersen_commitment_u64},
         Proof,
     },
     util::serial::{Encodable, SerialDecodable, SerialEncodable},
@@ -66,6 +67,17 @@ pub struct Builder {
 
 impl Builder {
     pub fn build(self, zk_bins: &ZkContractTable) -> FuncCall {
+        let total_funds = 110;
+        let total_funds_blind = pallas::Scalar::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_x = *total_funds_coords.x();
+        let total_funds_y = *total_funds_coords.y();
+        let total_funds = pallas::Base::from(total_funds);
+
+        let gov_token_blind = pallas::Base::random(&mut OsRng);
+        let token_commit = poseidon_hash::<2>([self.dao.gov_token_id, gov_token_blind]);
+
         let proposal_dest_coords = self.proposal.dest.0.to_affine().coordinates().unwrap();
         let proposal_dest_x = *proposal_dest_coords.x();
         let proposal_dest_y = *proposal_dest_coords.y();
@@ -102,14 +114,18 @@ impl Builder {
         };
         let zk_bin = zk_info.bincode.clone();
         let prover_witnesses = vec![
+            // Proposers total number of gov tokens
+            Witness::Base(Value::known(total_funds)),
+            Witness::Scalar(Value::known(total_funds_blind)),
+            // Used for blinding exported gov token ID
+            Witness::Base(Value::known(gov_token_blind)),
             // proposal params
-            //Witness::Base(Value::known(proposal_dest_x)),
-            //Witness::Base(Value::known(proposal_dest_y)),
-            //Witness::Base(Value::known(proposal_amount)),
-            //Witness::Base(Value::known(self.proposal.serial)),
-            //Witness::Base(Value::known(self.proposal.token_id)),
-            //Witness::Base(Value::known(self.proposal.blind)),
-
+            Witness::Base(Value::known(proposal_dest_x)),
+            Witness::Base(Value::known(proposal_dest_y)),
+            Witness::Base(Value::known(proposal_amount)),
+            Witness::Base(Value::known(self.proposal.serial)),
+            Witness::Base(Value::known(self.proposal.token_id)),
+            Witness::Base(Value::known(self.proposal.blind)),
             // DAO params
             Witness::Base(Value::known(dao_proposer_limit)),
             Witness::Base(Value::known(dao_quorum)),
@@ -121,14 +137,16 @@ impl Builder {
             Witness::Uint32(Value::known(dao_leaf_position.try_into().unwrap())),
             Witness::MerklePath(Value::known(self.dao_merkle_path.try_into().unwrap())),
         ];
-        let public_inputs = vec![self.dao_merkle_root.0];
+        let public_inputs =
+            vec![token_commit, self.dao_merkle_root.0, total_funds_x, total_funds_y];
         let circuit = ZkCircuit::new(prover_witnesses, zk_bin);
 
         let proving_key = &zk_info.proving_key;
         let main_proof = Proof::create(proving_key, &[circuit], &public_inputs, &mut OsRng)
             .expect("DAO::propose() proving error!");
 
-        let call_data = CallData { dao_merkle_root: self.dao_merkle_root };
+        let call_data =
+            CallData { dao_merkle_root: self.dao_merkle_root, token_commit, total_funds_commit };
 
         FuncCall {
             contract_id: "DAO".to_string(),