darkfi_dao_contract/client/
auth_xfer.rs
1use darkfi_money_contract::model::CoinAttributes;
20use darkfi_sdk::{
21 crypto::{note::ElGamalEncryptedNote, poseidon_hash, BaseBlind, PublicKey, SecretKey},
22 pasta::pallas,
23};
24
25use rand::rngs::OsRng;
26
27use darkfi::{
28 zk::{halo2::Value, Proof, ProvingKey, Witness, ZkCircuit},
29 zkas::ZkBinary,
30 Result,
31};
32
33use crate::model::{Dao, DaoAuthMoneyTransferParams, DaoProposal, VecAuthCallCommit};
34
35pub struct DaoAuthMoneyTransferCall {
36 pub proposal: DaoProposal,
37 pub proposal_coinattrs: Vec<CoinAttributes>,
38 pub dao: Dao,
39 pub input_user_data_blind: BaseBlind,
40 pub dao_coin_attrs: CoinAttributes,
41}
42
43impl DaoAuthMoneyTransferCall {
44 pub fn make(
45 self,
46 auth_xfer_zkbin: &ZkBinary,
47 auth_xfer_pk: &ProvingKey,
48 auth_xfer_enc_coin_zkbin: &ZkBinary,
49 auth_xfer_enc_coin_pk: &ProvingKey,
50 ) -> Result<(DaoAuthMoneyTransferParams, Vec<Proof>)> {
51 let mut proofs = vec![];
52
53 let mut enc_attrs = vec![];
56 let mut proposal_coinattrs = self.proposal_coinattrs;
57 proposal_coinattrs.push(self.dao_coin_attrs.clone());
58 for coin_attrs in proposal_coinattrs {
59 let coin = coin_attrs.to_coin();
60
61 let ephem_secret = SecretKey::random(&mut OsRng);
62 let ephem_pubkey = PublicKey::from_secret(ephem_secret);
63 let (ephem_x, ephem_y) = ephem_pubkey.xy();
64
65 let value_base = pallas::Base::from(coin_attrs.value);
66
67 let note = [
68 value_base,
69 coin_attrs.token_id.inner(),
70 coin_attrs.spend_hook.inner(),
71 coin_attrs.user_data,
72 coin_attrs.blind.inner(),
73 ];
74 let enc_note =
75 ElGamalEncryptedNote::encrypt_unsafe(note, &ephem_secret, &coin_attrs.public_key)?;
76
77 let prover_witnesses = vec![
78 Witness::EcNiPoint(Value::known(coin_attrs.public_key.inner())),
79 Witness::Base(Value::known(value_base)),
80 Witness::Base(Value::known(coin_attrs.token_id.inner())),
81 Witness::Base(Value::known(coin_attrs.spend_hook.inner())),
82 Witness::Base(Value::known(coin_attrs.user_data)),
83 Witness::Base(Value::known(coin_attrs.blind.inner())),
84 Witness::Base(Value::known(ephem_secret.inner())),
85 ];
86
87 let public_inputs = vec![
88 coin.inner(),
89 ephem_x,
90 ephem_y,
91 enc_note.encrypted_values[0],
92 enc_note.encrypted_values[1],
93 enc_note.encrypted_values[2],
94 enc_note.encrypted_values[3],
95 enc_note.encrypted_values[4],
96 ];
97
98 let circuit = ZkCircuit::new(prover_witnesses, auth_xfer_enc_coin_zkbin);
100 let proof =
101 Proof::create(auth_xfer_enc_coin_pk, &[circuit], &public_inputs, &mut OsRng)?;
102 proofs.push(proof);
103
104 enc_attrs.push(enc_note);
105 }
106
107 let ephem_secret = SecretKey::random(&mut OsRng);
110 let change_ephem_pubkey = PublicKey::from_secret(ephem_secret);
111 let (ephem_x, ephem_y) = change_ephem_pubkey.xy();
112
113 let dao_change_value = pallas::Base::from(self.dao_coin_attrs.value);
114
115 let note = [
116 dao_change_value,
117 self.dao_coin_attrs.token_id.inner(),
118 self.dao_coin_attrs.blind.inner(),
119 ];
120
121 let dao_change_attrs =
122 ElGamalEncryptedNote::encrypt_unsafe(note, &ephem_secret, &self.dao.notes_public_key)?;
123
124 let params = DaoAuthMoneyTransferParams { enc_attrs, dao_change_attrs };
125
126 let dao_proposer_limit = pallas::Base::from(self.dao.proposer_limit);
127 let dao_quorum = pallas::Base::from(self.dao.quorum);
128 let dao_early_exec_quorum = pallas::Base::from(self.dao.early_exec_quorum);
129 let dao_approval_ratio_quot = pallas::Base::from(self.dao.approval_ratio_quot);
130 let dao_approval_ratio_base = pallas::Base::from(self.dao.approval_ratio_base);
131 let dao_notes_public_key = self.dao.notes_public_key.inner();
132 let (dao_proposer_pub_x, dao_proposer_pub_y) = self.dao.proposer_public_key.xy();
133 let (dao_proposals_pub_x, dao_proposals_pub_y) = self.dao.proposals_public_key.xy();
134 let (dao_votes_pub_x, dao_votes_pub_y) = self.dao.votes_public_key.xy();
135 let (dao_exec_pub_x, dao_exec_pub_y) = self.dao.exec_public_key.xy();
136 let (dao_early_exec_pub_x, dao_early_exec_pub_y) = self.dao.early_exec_public_key.xy();
137
138 let input_user_data_enc =
139 poseidon_hash([self.dao.to_bulla().inner(), self.input_user_data_blind.inner()]);
140
141 let prover_witnesses = vec![
142 Witness::Base(Value::known(self.proposal.auth_calls.commit())),
144 Witness::Base(Value::known(pallas::Base::from(self.proposal.creation_blockwindow))),
145 Witness::Base(Value::known(pallas::Base::from(self.proposal.duration_blockwindows))),
146 Witness::Base(Value::known(self.proposal.user_data)),
147 Witness::Base(Value::known(self.proposal.blind.inner())),
148 Witness::Base(Value::known(dao_proposer_limit)),
150 Witness::Base(Value::known(dao_quorum)),
151 Witness::Base(Value::known(dao_early_exec_quorum)),
152 Witness::Base(Value::known(dao_approval_ratio_quot)),
153 Witness::Base(Value::known(dao_approval_ratio_base)),
154 Witness::Base(Value::known(self.dao.gov_token_id.inner())),
155 Witness::EcNiPoint(Value::known(dao_notes_public_key)),
156 Witness::Base(Value::known(dao_proposer_pub_x)),
157 Witness::Base(Value::known(dao_proposer_pub_y)),
158 Witness::Base(Value::known(dao_proposals_pub_x)),
159 Witness::Base(Value::known(dao_proposals_pub_y)),
160 Witness::Base(Value::known(dao_votes_pub_x)),
161 Witness::Base(Value::known(dao_votes_pub_y)),
162 Witness::Base(Value::known(dao_exec_pub_x)),
163 Witness::Base(Value::known(dao_exec_pub_y)),
164 Witness::Base(Value::known(dao_early_exec_pub_x)),
165 Witness::Base(Value::known(dao_early_exec_pub_y)),
166 Witness::Base(Value::known(self.dao.bulla_blind.inner())),
167 Witness::Base(Value::known(self.input_user_data_blind.inner())),
169 Witness::Base(Value::known(dao_change_value)),
171 Witness::Base(Value::known(self.dao_coin_attrs.token_id.inner())),
172 Witness::Base(Value::known(self.dao_coin_attrs.blind.inner())),
173 Witness::Base(Value::known(self.dao_coin_attrs.spend_hook.inner())),
175 Witness::Base(Value::known(ephem_secret.inner())),
177 ];
178
179 let public_inputs = vec![
180 self.proposal.to_bulla().inner(),
181 input_user_data_enc,
182 self.dao_coin_attrs.to_coin().inner(),
183 self.dao_coin_attrs.spend_hook.inner(),
184 self.proposal.auth_calls.commit(),
185 ephem_x,
186 ephem_y,
187 dao_change_attrs.encrypted_values[0],
188 dao_change_attrs.encrypted_values[1],
189 dao_change_attrs.encrypted_values[2],
190 ];
191
192 let circuit = ZkCircuit::new(prover_witnesses, auth_xfer_zkbin);
194 let proof = Proof::create(auth_xfer_pk, &[circuit], &public_inputs, &mut OsRng)?;
195 proofs.push(proof);
196
197 Ok((params, proofs))
198 }
199}