wallet.rs 5.9 KB

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