dao-exec.zk 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. constant "DaoExec" {
  2. EcFixedPointShort VALUE_COMMIT_VALUE,
  3. EcFixedPoint VALUE_COMMIT_RANDOM,
  4. }
  5. contract "DaoExec" {
  6. # proposal params
  7. Base proposal_dest_x,
  8. Base proposal_dest_y,
  9. Base proposal_amount,
  10. Base proposal_serial,
  11. Base proposal_token_id,
  12. Base proposal_blind,
  13. # DAO params
  14. Base dao_proposer_limit,
  15. Base dao_quorum,
  16. Base dao_approval_ratio_quot,
  17. Base dao_approval_ratio_base,
  18. Base gov_token_id,
  19. Base dao_public_x,
  20. Base dao_public_y,
  21. Base dao_bulla_blind,
  22. # votes
  23. Base yes_votes_value,
  24. Base all_votes_value,
  25. Scalar yes_votes_blind,
  26. Scalar all_votes_blind,
  27. # outputs + inputs
  28. Base user_serial,
  29. Base user_coin_blind,
  30. Base dao_serial,
  31. Base dao_coin_blind,
  32. Base input_value,
  33. Scalar input_value_blind,
  34. # misc
  35. Base dao_spend_hook,
  36. Base user_spend_hook,
  37. Base user_data,
  38. }
  39. circuit "DaoExec" {
  40. dao_bulla = poseidon_hash(
  41. dao_proposer_limit,
  42. dao_quorum,
  43. dao_approval_ratio_quot,
  44. dao_approval_ratio_base,
  45. gov_token_id,
  46. dao_public_x,
  47. dao_public_y,
  48. dao_bulla_blind,
  49. );
  50. # Proposal bulla is valid means DAO bulla is also valid
  51. # because of dao-propose-main.zk, already checks that when
  52. # we first create the proposal. So it is redundant here.
  53. proposal_bulla = poseidon_hash(
  54. proposal_dest_x,
  55. proposal_dest_y,
  56. proposal_amount,
  57. proposal_serial,
  58. proposal_token_id,
  59. dao_bulla,
  60. proposal_blind,
  61. # @tmp-workaround
  62. proposal_blind,
  63. );
  64. constrain_instance(proposal_bulla);
  65. coin_0 = poseidon_hash(
  66. proposal_dest_x,
  67. proposal_dest_y,
  68. proposal_amount,
  69. proposal_token_id,
  70. proposal_serial,
  71. user_spend_hook,
  72. user_data,
  73. proposal_blind,
  74. );
  75. constrain_instance(coin_0);
  76. change = base_sub(input_value, proposal_amount);
  77. coin_1 = poseidon_hash(
  78. dao_public_x,
  79. dao_public_y,
  80. change,
  81. proposal_token_id,
  82. dao_serial,
  83. dao_spend_hook,
  84. proposal_bulla,
  85. dao_coin_blind,
  86. );
  87. constrain_instance(coin_1);
  88. # Create pedersen commits for win_votes, and total_votes
  89. # and make public
  90. yes_votes_value_c = ec_mul_short(yes_votes_value, VALUE_COMMIT_VALUE);
  91. yes_votes_blind_c = ec_mul(yes_votes_blind, VALUE_COMMIT_RANDOM);
  92. yes_votes_commit = ec_add(yes_votes_value_c, yes_votes_blind_c);
  93. # get curve points and constrain
  94. yes_votes_commit_x = ec_get_x(yes_votes_commit);
  95. yes_votes_commit_y = ec_get_y(yes_votes_commit);
  96. constrain_instance(yes_votes_commit_x);
  97. constrain_instance(yes_votes_commit_y);
  98. all_votes_c = ec_mul_short(all_votes_value, VALUE_COMMIT_VALUE);
  99. all_votes_blind_c = ec_mul(all_votes_blind, VALUE_COMMIT_RANDOM);
  100. all_votes_commit = ec_add(all_votes_c, all_votes_blind_c);
  101. # get curve points and constrain
  102. all_votes_commit_x = ec_get_x(all_votes_commit);
  103. all_votes_commit_y = ec_get_y(all_votes_commit);
  104. constrain_instance(all_votes_commit_x);
  105. constrain_instance(all_votes_commit_y);
  106. # Create pedersen commit for input_value and make public
  107. input_value_v = ec_mul_short(input_value, VALUE_COMMIT_VALUE);
  108. input_value_r = ec_mul(input_value_blind, VALUE_COMMIT_RANDOM);
  109. input_value_commit = ec_add(input_value_v, input_value_r);
  110. # get curve points and constrain
  111. input_value_x = ec_get_x(input_value_commit);
  112. input_value_y = ec_get_y(input_value_commit);
  113. constrain_instance(input_value_x);
  114. constrain_instance(input_value_y);
  115. constrain_instance(dao_spend_hook);
  116. constrain_instance(user_spend_hook);
  117. constrain_instance(user_data);
  118. # Check that dao_quorum is less than or equal to all_votes_value
  119. one = witness_base(1);
  120. all_votes_value_1 = base_add(all_votes_value, one);
  121. less_than(dao_quorum, all_votes_value_1);
  122. # approval_ratio_quot / approval_ratio_base <= yes_votes / all_votes
  123. #
  124. # The above is also equivalent to this:
  125. #
  126. # all_votes * approval_ratio_quot <= yes_votes * approval_ratio_base
  127. rhs = base_mul(all_votes_value, dao_approval_ratio_quot);
  128. lhs = base_mul(yes_votes_value, dao_approval_ratio_base);
  129. lhs_1 = base_add(lhs, one);
  130. less_than(rhs, lhs_1);
  131. ####
  132. # Create coin 0
  133. # Create coin 1
  134. # Check values of coin 0 + coin 1 == input value
  135. # Check value of coin 0 == proposal_amount
  136. # Check public key matches too
  137. # Create the input value commit
  138. # Create the value commits
  139. # NOTE: there is a vulnerability here where someone can create the exec
  140. # transaction with a bad note so it cannot be decrypted by the receiver
  141. # TODO: research verifiable encryption inside ZK
  142. }