wallet.rs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. use log::debug;
  2. use rand::rngs::OsRng;
  3. use halo2_proofs::circuit::Value;
  4. use pasta_curves::{arithmetic::CurveAffine, group::Curve, pallas};
  5. use darkfi::{
  6. crypto::{util::pedersen_commitment_u64, Proof},
  7. zk::vm::{Witness, ZkCircuit},
  8. };
  9. use crate::{
  10. dao_contract::{
  11. exec::validate::CallData,
  12. propose::wallet::{DaoParams, Proposal},
  13. },
  14. demo::{FuncCall, ZkContractInfo, ZkContractTable},
  15. util::poseidon_hash,
  16. };
  17. pub struct Builder {
  18. pub proposal: Proposal,
  19. pub dao: DaoParams,
  20. pub win_votes: u64,
  21. pub total_votes: u64,
  22. pub win_votes_blind: pallas::Scalar,
  23. pub total_votes_blind: pallas::Scalar,
  24. pub user_serial: pallas::Base,
  25. pub user_coin_blind: pallas::Base,
  26. pub dao_serial: pallas::Base,
  27. pub dao_coin_blind: pallas::Base,
  28. pub input_value: u64,
  29. pub input_value_blind: pallas::Scalar,
  30. pub hook_dao_exec: pallas::Base,
  31. }
  32. impl Builder {
  33. pub fn build(self, zk_bins: &ZkContractTable) -> FuncCall {
  34. debug!(target: "dao_contract::exec::wallet::Builder", "build()");
  35. debug!(target: "dao_contract::exec::wallet", "proposalserial{:?}", self.proposal.serial);
  36. let mut proofs = vec![];
  37. let proposal_dest_coords = self.proposal.dest.0.to_affine().coordinates().unwrap();
  38. let proposal_amount = pallas::Base::from(self.proposal.amount);
  39. let dao_proposer_limit = pallas::Base::from(self.dao.proposer_limit);
  40. let dao_quorum = pallas::Base::from(self.dao.quorum);
  41. let dao_approval_ratio = pallas::Base::from(self.dao.approval_ratio);
  42. let dao_pubkey_coords = self.dao.public_key.0.to_affine().coordinates().unwrap();
  43. let user_spend_hook = pallas::Base::from(0);
  44. let user_data = pallas::Base::from(0);
  45. let input_value = pallas::Base::from(self.input_value);
  46. let change = input_value - proposal_amount;
  47. let dao_bulla = poseidon_hash::<8>([
  48. dao_proposer_limit,
  49. dao_quorum,
  50. dao_approval_ratio,
  51. self.dao.gov_token_id,
  52. *dao_pubkey_coords.x(),
  53. *dao_pubkey_coords.y(),
  54. self.dao.bulla_blind,
  55. // @tmp-workaround
  56. self.dao.bulla_blind,
  57. ]);
  58. let proposal_bulla = poseidon_hash::<8>([
  59. *proposal_dest_coords.x(),
  60. *proposal_dest_coords.y(),
  61. proposal_amount,
  62. self.proposal.serial,
  63. self.proposal.token_id,
  64. dao_bulla,
  65. self.proposal.blind,
  66. // @tmp-workaround
  67. self.proposal.blind,
  68. ]);
  69. let coin_0 = poseidon_hash::<8>([
  70. *proposal_dest_coords.x(),
  71. *proposal_dest_coords.y(),
  72. proposal_amount,
  73. self.proposal.token_id,
  74. self.proposal.serial,
  75. user_spend_hook,
  76. user_data,
  77. self.proposal.blind,
  78. ]);
  79. let coin_1 = poseidon_hash::<8>([
  80. *dao_pubkey_coords.x(),
  81. *dao_pubkey_coords.y(),
  82. change,
  83. self.proposal.token_id,
  84. self.dao_serial,
  85. self.hook_dao_exec,
  86. proposal_bulla,
  87. self.dao_coin_blind,
  88. ]);
  89. let win_votes_commit = pedersen_commitment_u64(self.win_votes, self.win_votes_blind);
  90. let win_votes_coords = win_votes_commit.to_affine().coordinates().unwrap();
  91. let total_votes_commit = pedersen_commitment_u64(self.total_votes, self.total_votes_blind);
  92. let total_votes_coords = total_votes_commit.to_affine().coordinates().unwrap();
  93. let input_value_commit = pedersen_commitment_u64(self.input_value, self.input_value_blind);
  94. let input_value_coords = input_value_commit.to_affine().coordinates().unwrap();
  95. let zk_info = zk_bins.lookup(&"dao-exec".to_string()).unwrap();
  96. let zk_info = if let ZkContractInfo::Binary(info) = zk_info {
  97. info
  98. } else {
  99. panic!("Not binary info")
  100. };
  101. let zk_bin = zk_info.bincode.clone();
  102. let prover_witnesses = vec![
  103. // proposal params
  104. Witness::Base(Value::known(*proposal_dest_coords.x())),
  105. Witness::Base(Value::known(*proposal_dest_coords.y())),
  106. Witness::Base(Value::known(proposal_amount)),
  107. Witness::Base(Value::known(self.proposal.serial)),
  108. Witness::Base(Value::known(self.proposal.token_id)),
  109. Witness::Base(Value::known(self.proposal.blind)),
  110. // DAO params
  111. Witness::Base(Value::known(dao_proposer_limit)),
  112. Witness::Base(Value::known(dao_quorum)),
  113. Witness::Base(Value::known(dao_approval_ratio)),
  114. Witness::Base(Value::known(self.dao.gov_token_id)),
  115. Witness::Base(Value::known(*dao_pubkey_coords.x())),
  116. Witness::Base(Value::known(*dao_pubkey_coords.y())),
  117. Witness::Base(Value::known(self.dao.bulla_blind)),
  118. // votes
  119. Witness::Base(Value::known(pallas::Base::from(self.win_votes))),
  120. Witness::Base(Value::known(pallas::Base::from(self.total_votes))),
  121. Witness::Scalar(Value::known(self.win_votes_blind)),
  122. Witness::Scalar(Value::known(self.total_votes_blind)),
  123. // outputs + inputs
  124. Witness::Base(Value::known(self.user_serial)),
  125. Witness::Base(Value::known(self.user_coin_blind)),
  126. Witness::Base(Value::known(self.dao_serial)),
  127. Witness::Base(Value::known(self.dao_coin_blind)),
  128. Witness::Base(Value::known(input_value)),
  129. Witness::Scalar(Value::known(self.input_value_blind)),
  130. // misc
  131. Witness::Base(Value::known(self.hook_dao_exec)),
  132. Witness::Base(Value::known(user_spend_hook)),
  133. Witness::Base(Value::known(user_data)),
  134. ];
  135. let public_inputs = vec![
  136. proposal_bulla,
  137. coin_0,
  138. coin_1,
  139. *win_votes_coords.x(),
  140. *win_votes_coords.y(),
  141. *total_votes_coords.x(),
  142. *total_votes_coords.y(),
  143. *input_value_coords.x(),
  144. *input_value_coords.y(),
  145. self.hook_dao_exec,
  146. user_spend_hook,
  147. user_data,
  148. ];
  149. let circuit = ZkCircuit::new(prover_witnesses, zk_bin);
  150. debug!(target: "example_contract::foo::wallet::Builder", "input_proof Proof::create()");
  151. let proving_key = &zk_info.proving_key;
  152. let input_proof = Proof::create(proving_key, &[circuit], &public_inputs, &mut OsRng)
  153. .expect("DAO::exec() proving error!)");
  154. proofs.push(input_proof);
  155. let call_data = CallData {
  156. proposal: proposal_bulla,
  157. coin_0,
  158. coin_1,
  159. win_votes_commit,
  160. total_votes_commit,
  161. input_value_commit,
  162. };
  163. FuncCall {
  164. contract_id: "DAO".to_string(),
  165. func_id: "DAO::exec()".to_string(),
  166. call_data: Box::new(call_data),
  167. proofs,
  168. }
  169. }
  170. }