1use core::str::FromStr;
20
21use darkfi_money_contract::model::{Nullifier, TokenId};
22use darkfi_sdk::{
23 crypto::{
24 note::{AeadEncryptedNote, ElGamalEncryptedNote},
25 pasta_prelude::*,
26 poseidon_hash, BaseBlind, ContractId, MerkleNode, PublicKey,
27 },
28 error::ContractError,
29 pasta::pallas,
30};
31use darkfi_serial::{Encodable, SerialDecodable, SerialEncodable};
32
33#[cfg(feature = "client")]
34use darkfi_serial::async_trait;
35
36#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
37pub struct Dao {
40 pub proposer_limit: u64,
42 pub quorum: u64,
44 pub early_exec_quorum: u64,
48 pub approval_ratio_quot: u64,
50 pub approval_ratio_base: u64,
51 pub gov_token_id: TokenId,
53 pub notes_public_key: PublicKey,
55 pub proposer_public_key: PublicKey,
57 pub proposals_public_key: PublicKey,
59 pub votes_public_key: PublicKey,
61 pub exec_public_key: PublicKey,
63 pub early_exec_public_key: PublicKey,
65 pub bulla_blind: BaseBlind,
67}
68impl Dao {
71 pub fn to_bulla(&self) -> DaoBulla {
72 let proposer_limit = pallas::Base::from(self.proposer_limit);
73 let quorum = pallas::Base::from(self.quorum);
74 let early_exec_quorum = pallas::Base::from(self.early_exec_quorum);
75 let approval_ratio_quot = pallas::Base::from(self.approval_ratio_quot);
76 let approval_ratio_base = pallas::Base::from(self.approval_ratio_base);
77 let (notes_pub_x, notes_pub_y) = self.notes_public_key.xy();
78 let (proposer_pub_x, proposer_pub_y) = self.proposer_public_key.xy();
79 let (proposals_pub_x, proposals_pub_y) = self.proposals_public_key.xy();
80 let (votes_pub_x, votes_pub_y) = self.votes_public_key.xy();
81 let (exec_pub_x, exec_pub_y) = self.exec_public_key.xy();
82 let (early_exec_pub_x, early_exec_pub_y) = self.early_exec_public_key.xy();
83 let bulla = poseidon_hash([
84 proposer_limit,
85 quorum,
86 early_exec_quorum,
87 approval_ratio_quot,
88 approval_ratio_base,
89 self.gov_token_id.inner(),
90 notes_pub_x,
91 notes_pub_y,
92 proposer_pub_x,
93 proposer_pub_y,
94 proposals_pub_x,
95 proposals_pub_y,
96 votes_pub_x,
97 votes_pub_y,
98 exec_pub_x,
99 exec_pub_y,
100 early_exec_pub_x,
101 early_exec_pub_y,
102 self.bulla_blind.inner(),
103 ]);
104 DaoBulla(bulla)
105 }
106}
107
108#[derive(Debug, Copy, Clone, Eq, PartialEq, SerialEncodable, SerialDecodable)]
110pub struct DaoBulla(pallas::Base);
111
112impl DaoBulla {
113 pub fn inner(&self) -> pallas::Base {
115 self.0
116 }
117
118 pub fn from_bytes(x: [u8; 32]) -> Result<Self, ContractError> {
121 match pallas::Base::from_repr(x).into() {
122 Some(v) => Ok(Self(v)),
123 None => {
124 Err(ContractError::IoError("Failed to instantiate DaoBulla from bytes".to_string()))
125 }
126 }
127 }
128
129 pub fn to_bytes(&self) -> [u8; 32] {
131 self.0.to_repr()
132 }
133}
134
135impl std::hash::Hash for DaoBulla {
136 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
137 state.write(&self.to_bytes());
138 }
139}
140
141darkfi_sdk::fp_from_bs58!(DaoBulla);
142darkfi_sdk::fp_to_bs58!(DaoBulla);
143darkfi_sdk::ty_from_fp!(DaoBulla);
144
145#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
146pub struct DaoAuthCall {
148 pub contract_id: ContractId,
149 pub function_code: u8,
150 pub auth_data: Vec<u8>,
151}
152pub trait VecAuthCallCommit {
155 fn commit(&self) -> pallas::Base;
156}
157
158impl VecAuthCallCommit for Vec<DaoAuthCall> {
159 fn commit(&self) -> pallas::Base {
160 let mut hasher =
171 blake2b_simd::Params::new().hash_length(64).personal(b"justDAOthings").to_state();
172 self.encode(&mut hasher).unwrap();
173 let hash = hasher.finalize();
174 let bytes = hash.as_array();
175 pallas::Base::from_uniform_bytes(bytes)
176 }
177}
178
179#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
180pub struct DaoProposal {
182 pub auth_calls: Vec<DaoAuthCall>,
183 pub creation_blockwindow: u64,
184 pub duration_blockwindows: u64,
185 pub user_data: pallas::Base,
187 pub dao_bulla: DaoBulla,
188 pub blind: BaseBlind,
189}
190impl DaoProposal {
193 pub fn to_bulla(&self) -> DaoProposalBulla {
194 let bulla = poseidon_hash([
195 self.auth_calls.commit(),
196 pallas::Base::from(self.creation_blockwindow),
197 pallas::Base::from(self.duration_blockwindows),
198 self.user_data,
199 self.dao_bulla.inner(),
200 self.blind.inner(),
201 ]);
202 DaoProposalBulla(bulla)
203 }
204}
205
206#[derive(Debug, Copy, Clone, Eq, PartialEq, SerialEncodable, SerialDecodable)]
208pub struct DaoProposalBulla(pallas::Base);
209
210impl DaoProposalBulla {
211 pub fn inner(&self) -> pallas::Base {
213 self.0
214 }
215
216 pub fn from_bytes(x: [u8; 32]) -> Result<Self, ContractError> {
219 match pallas::Base::from_repr(x).into() {
220 Some(v) => Ok(Self(v)),
221 None => Err(ContractError::IoError(
222 "Failed to instantiate DaoProposalBulla from bytes".to_string(),
223 )),
224 }
225 }
226
227 pub fn to_bytes(&self) -> [u8; 32] {
229 self.0.to_repr()
230 }
231}
232
233impl std::hash::Hash for DaoProposalBulla {
234 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
235 state.write(&self.to_bytes());
236 }
237}
238
239darkfi_sdk::fp_from_bs58!(DaoProposalBulla);
240darkfi_sdk::fp_to_bs58!(DaoProposalBulla);
241darkfi_sdk::ty_from_fp!(DaoProposalBulla);
242
243#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
244pub struct DaoMintParams {
247 pub dao_bulla: DaoBulla,
249 pub dao_pubkey: PublicKey,
251}
252#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
256pub struct DaoMintUpdate {
257 pub dao_bulla: DaoBulla,
259}
260
261#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
262pub struct DaoProposeParams {
265 pub dao_merkle_root: MerkleNode,
267 pub token_commit: pallas::Base,
269 pub proposal_bulla: DaoProposalBulla,
271 pub note: AeadEncryptedNote,
273 pub inputs: Vec<DaoProposeParamsInput>,
275}
276#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
279pub struct DaoProposeParamsInput {
282 pub value_commit: pallas::Point,
284 pub merkle_coin_root: MerkleNode,
286 pub smt_null_root: pallas::Base,
288 pub signature_public: PublicKey,
290}
291#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
295pub struct DaoProposeUpdate {
296 pub proposal_bulla: DaoProposalBulla,
298 pub snapshot_coins: MerkleNode,
300 pub snapshot_nulls: pallas::Base,
302}
303
304#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
306pub struct DaoProposalMetadata {
307 pub vote_aggregate: DaoBlindAggregateVote,
309 pub snapshot_coins: MerkleNode,
311 pub snapshot_nulls: pallas::Base,
313}
314
315#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
316pub struct DaoVoteParams {
319 pub token_commit: pallas::Base,
321 pub proposal_bulla: DaoProposalBulla,
323 pub yes_vote_commit: pallas::Point,
325 pub note: ElGamalEncryptedNote<4>,
327 pub inputs: Vec<DaoVoteParamsInput>,
329}
330#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
333pub struct DaoVoteParamsInput {
336 pub vote_commit: pallas::Point,
338 pub vote_nullifier: Nullifier,
340 pub signature_public: PublicKey,
342}
343#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
347pub struct DaoVoteUpdate {
348 pub proposal_bulla: DaoProposalBulla,
350 pub proposal_metadata: DaoProposalMetadata,
352 pub vote_nullifiers: Vec<Nullifier>,
354}
355
356#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
357pub struct DaoBlindAggregateVote {
361 pub yes_vote_commit: pallas::Point,
363 pub all_vote_commit: pallas::Point,
365}
366impl DaoBlindAggregateVote {
369 pub fn aggregate(&mut self, other: Self) {
371 self.yes_vote_commit += other.yes_vote_commit;
372 self.all_vote_commit += other.all_vote_commit;
373 }
374}
375
376impl Default for DaoBlindAggregateVote {
377 fn default() -> Self {
378 Self {
379 yes_vote_commit: pallas::Point::identity(),
380 all_vote_commit: pallas::Point::identity(),
381 }
382 }
383}
384
385#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
386pub struct DaoExecParams {
389 pub proposal_bulla: DaoProposalBulla,
391 pub proposal_auth_calls: Vec<DaoAuthCall>,
393 pub blind_total_vote: DaoBlindAggregateVote,
395 pub early_exec: bool,
397 pub signature_public: PublicKey,
400}
401#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
405pub struct DaoExecUpdate {
406 pub proposal_bulla: DaoProposalBulla,
408}
409
410#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
411pub struct DaoAuthMoneyTransferParams {
414 pub enc_attrs: Vec<ElGamalEncryptedNote<5>>,
415 pub dao_change_attrs: ElGamalEncryptedNote<3>,
416}
417