Преглед изворни кода

DAO::exec(): add missing signature

zero пре 2 година
родитељ
комит
8b3dee989d

+ 9 - 0
src/contract/dao/proof/dao-exec.zk

@@ -4,6 +4,7 @@ field = "pallas";
 constant "DaoExec" {
     EcFixedPointShort VALUE_COMMIT_VALUE,
     EcFixedPoint VALUE_COMMIT_RANDOM,
+    EcFixedPointBase NULLIFIER_K,
 }
 
 witness "DaoExec" {
@@ -29,6 +30,9 @@ witness "DaoExec" {
     Base all_vote_value,
     Scalar yes_vote_blind,
     Scalar all_vote_blind,
+
+    # Signature secret
+    Base signature_secret,
 }
 
 circuit "DaoExec" {
@@ -85,5 +89,10 @@ circuit "DaoExec" {
     rhs = base_mul(yes_vote_value, dao_approval_ratio_base);
     rhs_1 = base_add(rhs, one);
     less_than_strict(lhs, rhs_1);
+
+    # Derive a public key for the signature and constrain its coordinates
+    signature_public = ec_mul_base(signature_secret, NULLIFIER_K);
+    constrain_instance(ec_get_x(signature_public));
+    constrain_instance(ec_get_y(signature_public));
 }
 

+ 8 - 1
src/contract/dao/src/client/exec.rs

@@ -17,7 +17,7 @@
  */
 
 use darkfi_sdk::{
-    crypto::{pasta_prelude::*, pedersen_commitment_u64, SecretKey},
+    crypto::{pasta_prelude::*, pedersen_commitment_u64, PublicKey, SecretKey},
     pasta::pallas,
 };
 
@@ -74,6 +74,8 @@ impl DaoExecCall {
 
         let proposal_auth_calls_commit = self.proposal.auth_calls.commit();
 
+        let signature_public = PublicKey::from_secret(self.signature_secret);
+
         let prover_witnesses = vec![
             // proposal params
             Witness::Base(Value::known(proposal_auth_calls_commit)),
@@ -95,6 +97,8 @@ impl DaoExecCall {
             Witness::Base(Value::known(pallas::Base::from(self.all_vote_value))),
             Witness::Scalar(Value::known(self.yes_vote_blind)),
             Witness::Scalar(Value::known(self.all_vote_blind)),
+            // signature secret
+            Witness::Base(Value::known(self.signature_secret.inner())),
         ];
 
         debug!(target: "dao", "proposal_bulla: {:?}", proposal_bulla);
@@ -105,6 +109,8 @@ impl DaoExecCall {
             *yes_vote_commit_coords.y(),
             *all_vote_commit_coords.x(),
             *all_vote_commit_coords.y(),
+            signature_public.x(),
+            signature_public.y(),
         ];
         //export_witness_json("witness.json", &prover_witnesses, &public_inputs);
 
@@ -116,6 +122,7 @@ impl DaoExecCall {
             proposal_bulla,
             proposal_auth_calls: self.proposal.auth_calls,
             blind_total_vote: DaoBlindAggregateVote { yes_vote_commit, all_vote_commit },
+            signature_public,
         };
 
         Ok((params, proofs))

+ 3 - 1
src/contract/dao/src/entrypoint/exec.rs

@@ -45,7 +45,7 @@ pub(crate) fn dao_exec_get_metadata(
     // Public inputs for the ZK proofs we have to verify
     let mut zk_public_inputs: Vec<(String, Vec<pallas::Base>)> = vec![];
     // Public keys for the transaction signatures we have to verify
-    let signature_pubkeys: Vec<PublicKey> = vec![];
+    let signature_pubkeys: Vec<PublicKey> = vec![params.signature_public];
 
     let blind_vote = params.blind_total_vote;
     let yes_vote_coords = blind_vote.yes_vote_commit.to_affine().coordinates().unwrap();
@@ -60,6 +60,8 @@ pub(crate) fn dao_exec_get_metadata(
             *yes_vote_coords.y(),
             *all_vote_coords.x(),
             *all_vote_coords.y(),
+            params.signature_public.x(),
+            params.signature_public.y(),
         ],
     ));
 

+ 3 - 0
src/contract/dao/src/model.rs

@@ -351,6 +351,9 @@ pub struct DaoExecParams {
     pub proposal_auth_calls: Vec<DaoAuthCall>,
     /// Aggregated blinds for the vote commitments
     pub blind_total_vote: DaoBlindAggregateVote,
+    /// Public key for the signature.
+    /// The signature ensures this DAO::exec call cannot be modified with other calls.
+    pub signature_public: PublicKey,
 }
 // ANCHOR_END: dao-exec-params
 

+ 1 - 2
src/contract/test-harness/src/dao_exec.rs

@@ -78,7 +78,6 @@ impl TestHarness {
         let timer = Instant::now();
 
         let input_user_data_blind = pallas::Base::random(&mut OsRng);
-        // TODO: FIXME: This is not checked anywhere!
         let exec_signature_secret = SecretKey::random(&mut OsRng);
 
         assert!(!proposal_coinattrs.is_empty());
@@ -221,7 +220,7 @@ impl TestHarness {
         };
         let auth_xfer_sigs = vec![];
         let xfer_sigs = tx.create_sigs(&mut OsRng, &xfer_secrets.signature_secrets)?;
-        let exec_sigs = tx.create_sigs(&mut OsRng, &[])?;
+        let exec_sigs = tx.create_sigs(&mut OsRng, &[exec_signature_secret])?;
         tx.signatures = vec![auth_xfer_sigs, xfer_sigs, exec_sigs];
         tx_action_benchmark.creation_times.push(timer.elapsed());