exec.rs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2022 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use darkfi_sdk::crypto::{
  19. pallas, pasta_prelude::*, pedersen_commitment_u64, poseidon_hash, SecretKey,
  20. };
  21. use halo2_proofs::circuit::Value;
  22. use log::debug;
  23. use rand::rngs::OsRng;
  24. use darkfi::{
  25. zk::{Proof, ProvingKey, Witness, ZkCircuit},
  26. zkas::ZkBinary,
  27. Result,
  28. };
  29. use super::{DaoInfo, ProposalInfo};
  30. use crate::dao_model::DaoExecParams;
  31. pub struct ExecCall {
  32. pub proposal: ProposalInfo,
  33. pub dao: DaoInfo,
  34. pub yes_votes_value: u64,
  35. pub all_votes_value: u64,
  36. pub yes_votes_blind: pallas::Scalar,
  37. pub all_votes_blind: pallas::Scalar,
  38. pub user_serial: pallas::Base,
  39. pub user_coin_blind: pallas::Base,
  40. pub dao_serial: pallas::Base,
  41. pub dao_coin_blind: pallas::Base,
  42. pub input_value: u64,
  43. pub input_value_blind: pallas::Scalar,
  44. pub hook_dao_exec: pallas::Base,
  45. pub signature_secret: SecretKey,
  46. }
  47. impl ExecCall {
  48. pub fn make(
  49. self,
  50. exec_zkbin: &ZkBinary,
  51. exec_pk: &ProvingKey,
  52. ) -> Result<(DaoExecParams, Vec<Proof>)> {
  53. debug!(target: "dao", "build()");
  54. let mut proofs = vec![];
  55. let (proposal_dest_x, proposal_dest_y) = self.proposal.dest.xy();
  56. let proposal_amount = pallas::Base::from(self.proposal.amount);
  57. let dao_proposer_limit = pallas::Base::from(self.dao.proposer_limit);
  58. let dao_quorum = pallas::Base::from(self.dao.quorum);
  59. let dao_approval_ratio_quot = pallas::Base::from(self.dao.approval_ratio_quot);
  60. let dao_approval_ratio_base = pallas::Base::from(self.dao.approval_ratio_base);
  61. let (dao_pub_x, dao_pub_y) = self.dao.public_key.xy();
  62. let user_spend_hook = pallas::Base::from(0);
  63. let user_data = pallas::Base::from(0);
  64. let input_value = pallas::Base::from(self.input_value);
  65. let change = input_value - proposal_amount;
  66. let dao_bulla = poseidon_hash::<8>([
  67. dao_proposer_limit,
  68. dao_quorum,
  69. dao_approval_ratio_quot,
  70. dao_approval_ratio_base,
  71. self.dao.gov_token_id.inner(),
  72. dao_pub_x,
  73. dao_pub_y,
  74. self.dao.bulla_blind,
  75. ]);
  76. let proposal_bulla = poseidon_hash::<8>([
  77. proposal_dest_x,
  78. proposal_dest_y,
  79. proposal_amount,
  80. self.proposal.serial,
  81. self.proposal.token_id.inner(),
  82. dao_bulla,
  83. self.proposal.blind,
  84. // @tmp-workaround
  85. self.proposal.blind,
  86. ]);
  87. let coin_0 = poseidon_hash::<8>([
  88. proposal_dest_x,
  89. proposal_dest_y,
  90. proposal_amount,
  91. self.proposal.token_id.inner(),
  92. self.proposal.serial,
  93. user_spend_hook,
  94. user_data,
  95. self.proposal.blind,
  96. ]);
  97. let coin_1 = poseidon_hash::<8>([
  98. dao_pub_x,
  99. dao_pub_y,
  100. change,
  101. self.proposal.token_id.inner(),
  102. self.dao_serial,
  103. self.hook_dao_exec,
  104. dao_bulla,
  105. self.dao_coin_blind,
  106. ]);
  107. let yes_votes_commit = pedersen_commitment_u64(self.yes_votes_value, self.yes_votes_blind);
  108. let yes_votes_commit_coords = yes_votes_commit.to_affine().coordinates().unwrap();
  109. let all_votes_commit = pedersen_commitment_u64(self.all_votes_value, self.all_votes_blind);
  110. let all_votes_commit_coords = all_votes_commit.to_affine().coordinates().unwrap();
  111. let input_value_commit = pedersen_commitment_u64(self.input_value, self.input_value_blind);
  112. let input_value_commit_coords = input_value_commit.to_affine().coordinates().unwrap();
  113. let prover_witnesses = vec![
  114. // proposal params
  115. Witness::Base(Value::known(proposal_dest_x)),
  116. Witness::Base(Value::known(proposal_dest_y)),
  117. Witness::Base(Value::known(proposal_amount)),
  118. Witness::Base(Value::known(self.proposal.serial)),
  119. Witness::Base(Value::known(self.proposal.token_id.inner())),
  120. Witness::Base(Value::known(self.proposal.blind)),
  121. // DAO params
  122. Witness::Base(Value::known(dao_proposer_limit)),
  123. Witness::Base(Value::known(dao_quorum)),
  124. Witness::Base(Value::known(dao_approval_ratio_quot)),
  125. Witness::Base(Value::known(dao_approval_ratio_base)),
  126. Witness::Base(Value::known(self.dao.gov_token_id.inner())),
  127. Witness::Base(Value::known(dao_pub_x)),
  128. Witness::Base(Value::known(dao_pub_y)),
  129. Witness::Base(Value::known(self.dao.bulla_blind)),
  130. // votes
  131. Witness::Base(Value::known(pallas::Base::from(self.yes_votes_value))),
  132. Witness::Base(Value::known(pallas::Base::from(self.all_votes_value))),
  133. Witness::Scalar(Value::known(self.yes_votes_blind)),
  134. Witness::Scalar(Value::known(self.all_votes_blind)),
  135. // outputs + inputs
  136. Witness::Base(Value::known(self.user_serial)),
  137. Witness::Base(Value::known(self.user_coin_blind)),
  138. Witness::Base(Value::known(self.dao_serial)),
  139. Witness::Base(Value::known(self.dao_coin_blind)),
  140. Witness::Base(Value::known(input_value)),
  141. Witness::Scalar(Value::known(self.input_value_blind)),
  142. // misc
  143. Witness::Base(Value::known(self.hook_dao_exec)),
  144. Witness::Base(Value::known(user_spend_hook)),
  145. Witness::Base(Value::known(user_data)),
  146. ];
  147. debug!("proposal_bulla: {:?}", proposal_bulla);
  148. let public_inputs = vec![
  149. proposal_bulla,
  150. coin_0,
  151. coin_1,
  152. *yes_votes_commit_coords.x(),
  153. *yes_votes_commit_coords.y(),
  154. *all_votes_commit_coords.x(),
  155. *all_votes_commit_coords.y(),
  156. *input_value_commit_coords.x(),
  157. *input_value_commit_coords.y(),
  158. self.hook_dao_exec,
  159. user_spend_hook,
  160. user_data,
  161. ];
  162. let circuit = ZkCircuit::new(prover_witnesses, exec_zkbin.clone());
  163. let input_proof = Proof::create(&exec_pk, &[circuit], &public_inputs, &mut OsRng)
  164. .expect("DAO::exec() proving error!)");
  165. proofs.push(input_proof);
  166. let params = DaoExecParams {
  167. proposal: proposal_bulla,
  168. coin_0,
  169. coin_1,
  170. yes_votes_commit,
  171. all_votes_commit,
  172. input_value_commit,
  173. };
  174. Ok((params, proofs))
  175. }
  176. }