darkfi_dao_contract/client/
exec.rs
1use darkfi_sdk::{
20 crypto::{pasta_prelude::*, pedersen_commitment_u64, PublicKey, ScalarBlind, SecretKey},
21 pasta::pallas,
22};
23
24use log::debug;
25use rand::rngs::OsRng;
26
27use darkfi::{
28 zk::{halo2::Value, Proof, ProvingKey, Witness, ZkCircuit},
29 zkas::ZkBinary,
30 ClientFailed, Result,
31};
32
33use crate::{
34 error::DaoError,
35 model::{Dao, DaoBlindAggregateVote, DaoExecParams, DaoProposal, VecAuthCallCommit},
36};
37
38pub struct DaoExecCall {
39 pub proposal: DaoProposal,
40 pub dao: Dao,
41 pub yes_vote_value: u64,
42 pub all_vote_value: u64,
43 pub yes_vote_blind: ScalarBlind,
44 pub all_vote_blind: ScalarBlind,
45 pub signature_secret: SecretKey,
46 pub current_blockwindow: u64,
47}
48
49impl DaoExecCall {
50 pub fn make(
51 self,
52 dao_exec_secret_key: &SecretKey,
53 dao_early_exec_secret_key: &Option<SecretKey>,
54 exec_zkbin: &ZkBinary,
55 exec_pk: &ProvingKey,
56 ) -> Result<(DaoExecParams, Vec<Proof>)> {
57 debug!(target: "contract::dao::client::exec", "build()");
58 let mut proofs = vec![];
59
60 let dao_proposer_limit = pallas::Base::from(self.dao.proposer_limit);
61 let dao_quorum = pallas::Base::from(self.dao.quorum);
62 let dao_early_exec_quorum = pallas::Base::from(self.dao.early_exec_quorum);
63 let dao_approval_ratio_quot = pallas::Base::from(self.dao.approval_ratio_quot);
64 let dao_approval_ratio_base = pallas::Base::from(self.dao.approval_ratio_base);
65 let (dao_notes_pub_x, dao_notes_pub_y) = self.dao.notes_public_key.xy();
66 let (dao_proposer_pub_x, dao_proposer_pub_y) = self.dao.proposer_public_key.xy();
67 let (dao_proposals_pub_x, dao_proposals_pub_y) = self.dao.proposals_public_key.xy();
68 let (dao_votes_pub_x, dao_votes_pub_y) = self.dao.votes_public_key.xy();
69
70 let dao_bulla = self.dao.to_bulla();
71 if dao_bulla != self.proposal.dao_bulla {
72 return Err(ClientFailed::VerifyError(DaoError::InvalidCalls.to_string()).into())
73 }
74 let proposal_bulla = self.proposal.to_bulla();
75
76 let yes_vote_commit = pedersen_commitment_u64(self.yes_vote_value, self.yes_vote_blind);
77 let yes_vote_commit_coords = yes_vote_commit.to_affine().coordinates().unwrap();
78
79 let all_vote_commit = pedersen_commitment_u64(self.all_vote_value, self.all_vote_blind);
80 let all_vote_commit_coords = all_vote_commit.to_affine().coordinates().unwrap();
81
82 let proposal_auth_calls_commit = self.proposal.auth_calls.commit();
83
84 let signature_public = PublicKey::from_secret(self.signature_secret);
85
86 let current_blockwindow = pallas::Base::from(self.current_blockwindow);
87
88 let mut prover_witnesses = vec![
89 Witness::Base(Value::known(proposal_auth_calls_commit)),
91 Witness::Base(Value::known(pallas::Base::from(self.proposal.creation_blockwindow))),
92 Witness::Base(Value::known(pallas::Base::from(self.proposal.duration_blockwindows))),
93 Witness::Base(Value::known(self.proposal.user_data)),
94 Witness::Base(Value::known(self.proposal.blind.inner())),
95 Witness::Base(Value::known(dao_proposer_limit)),
97 Witness::Base(Value::known(dao_quorum)),
98 Witness::Base(Value::known(dao_early_exec_quorum)),
99 Witness::Base(Value::known(dao_approval_ratio_quot)),
100 Witness::Base(Value::known(dao_approval_ratio_base)),
101 Witness::Base(Value::known(self.dao.gov_token_id.inner())),
102 Witness::Base(Value::known(dao_notes_pub_x)),
103 Witness::Base(Value::known(dao_notes_pub_y)),
104 Witness::Base(Value::known(dao_proposer_pub_x)),
105 Witness::Base(Value::known(dao_proposer_pub_y)),
106 Witness::Base(Value::known(dao_proposals_pub_x)),
107 Witness::Base(Value::known(dao_proposals_pub_y)),
108 Witness::Base(Value::known(dao_votes_pub_x)),
109 Witness::Base(Value::known(dao_votes_pub_y)),
110 Witness::Base(Value::known(dao_exec_secret_key.inner())),
111 ];
112 match dao_early_exec_secret_key {
114 Some(dao_early_exec_secret_key) => prover_witnesses
115 .push(Witness::Base(Value::known(dao_early_exec_secret_key.inner()))),
116 None => {
117 let (dao_early_exec_pub_x, dao_early_exec_pub_y) =
118 self.dao.early_exec_public_key.xy();
119 prover_witnesses.push(Witness::Base(Value::known(dao_early_exec_pub_x)));
120 prover_witnesses.push(Witness::Base(Value::known(dao_early_exec_pub_y)));
121 }
122 };
123 prover_witnesses.extend_from_slice(&[
125 Witness::Base(Value::known(self.dao.bulla_blind.inner())),
126 Witness::Base(Value::known(pallas::Base::from(self.yes_vote_value))),
128 Witness::Base(Value::known(pallas::Base::from(self.all_vote_value))),
129 Witness::Scalar(Value::known(self.yes_vote_blind.inner())),
130 Witness::Scalar(Value::known(self.all_vote_blind.inner())),
131 Witness::Base(Value::known(current_blockwindow)),
133 Witness::Base(Value::known(self.signature_secret.inner())),
135 ]);
136
137 debug!(target: "contract::dao::client::exec", "proposal_bulla: {:?}", proposal_bulla);
138 let public_inputs = vec![
139 proposal_bulla.inner(),
140 proposal_auth_calls_commit,
141 current_blockwindow,
142 *yes_vote_commit_coords.x(),
143 *yes_vote_commit_coords.y(),
144 *all_vote_commit_coords.x(),
145 *all_vote_commit_coords.y(),
146 signature_public.x(),
147 signature_public.y(),
148 ];
149 let circuit = ZkCircuit::new(prover_witnesses, exec_zkbin);
152 let input_proof = Proof::create(exec_pk, &[circuit], &public_inputs, &mut OsRng)?;
153 proofs.push(input_proof);
154
155 let params = DaoExecParams {
156 proposal_bulla,
157 proposal_auth_calls: self.proposal.auth_calls,
158 blind_total_vote: DaoBlindAggregateVote { yes_vote_commit, all_vote_commit },
159 early_exec: dao_early_exec_secret_key.is_some(),
160 signature_public,
161 };
162
163 Ok((params, proofs))
164 }
165}