Prechádzať zdrojové kódy

change proposer code to export commits to total win votes and total votes instead of directional votes

narodnik 4 rokov pred
rodič
commit
724b94b33b
3 zmenil súbory, kde vykonal 121 pridanie a 67 odobranie
  1. 5 2
      bin/daod/demo/crypto.py
  2. 110 64
      bin/daod/demo/main.py
  3. 6 1
      bin/daod/demo/money.py

+ 5 - 2
bin/daod/demo/crypto.py

@@ -24,13 +24,14 @@ def ff_inv(a, p):
 
 
 class EllipticCurve:
 class EllipticCurve:
 
 
-    def __init__(self, p, A, B, order, G, H):
+    def __init__(self, p, A, B, order, G, H, J):
         self.p = p
         self.p = p
         self.A = A
         self.A = A
         self.B = B
         self.B = B
         self.order = order
         self.order = order
         self.G = G
         self.G = G
         self.H = H
         self.H = H
+        self.J = J
         assert self.is_valid(G)
         assert self.is_valid(G)
         assert self.is_valid(H)
         assert self.is_valid(H)
 
 
@@ -93,7 +94,9 @@ def pallas_curve():
     G = (5, 5392431450607408583390510508521091931943415030464003135511088002453056875732, 1)
     G = (5, 5392431450607408583390510508521091931943415030464003135511088002453056875732, 1)
     H = (9762257241998025279988087154025308614062019274413483967640476725944341089207,
     H = (9762257241998025279988087154025308614062019274413483967640476725944341089207,
          12058632856930756995627167820351407063813260358041446014729496773111030695755, 1)
          12058632856930756995627167820351407063813260358041446014729496773111030695755, 1)
-    ec = EllipticCurve(p, 0, 5, q, G, H)
+    J = (7795559447963065356059848000022900528974048197507738248625163674930282081839,
+         5156492880772775379342191094371887365795329446468828588866320184016504353483, 1)
+    ec = EllipticCurve(p, 0, 5, q, G, H, J)
     A = (144931808354919915876542440378319484704499556634959420306426167479163065488,
     A = (144931808354919915876542440378319484704499556634959420306426167479163065488,
          2699682121356767698440748624399854659825391162912545787181017961871465868196, 1)
          2699682121356767698440748624399854659825391162912545787181017961871465868196, 1)
     B = (16017037670495191561606513965775243786961447026019262496667491008912834496943,
     B = (16017037670495191561606513965775243786961447026019262496667491008912834496943,

+ 110 - 64
bin/daod/demo/main.py

@@ -101,8 +101,9 @@ class ProposerTxBuilder:
             # Proposal
             # Proposal
             self.proposal.dest,
             self.proposal.dest,
             self.proposal.amount,
             self.proposal.amount,
-            self.proposal.blind,
             self.proposal.serial,
             self.proposal.serial,
+            self.proposal.token_id,
+            self.proposal.blind,
             # Merkle witness
             # Merkle witness
             self.all_dao_bullas,
             self.all_dao_bullas,
             self.ec
             self.ec
@@ -262,8 +263,8 @@ class ProposerTxDaoProof:
                  proposer_limit, quorum, approval_ratio,
                  proposer_limit, quorum, approval_ratio,
                  gov_token_id, dao_bulla_blind,
                  gov_token_id, dao_bulla_blind,
                  token_blind, enc_bulla_blind,
                  token_blind, enc_bulla_blind,
-                 proposal_dest, proposal_amount, proposal_blind,
-                 proposal_serial,
+                 proposal_dest, proposal_amount, proposal_serial,
+                 proposal_token_id, proposal_blind,
                  all_dao_bullas, ec):
                  all_dao_bullas, ec):
         self.total_value = total_value
         self.total_value = total_value
         self.total_value_blinds = total_value_blinds
         self.total_value_blinds = total_value_blinds
@@ -276,8 +277,9 @@ class ProposerTxDaoProof:
         self.enc_bulla_blind = enc_bulla_blind
         self.enc_bulla_blind = enc_bulla_blind
         self.proposal_dest = proposal_dest
         self.proposal_dest = proposal_dest
         self.proposal_amount = proposal_amount
         self.proposal_amount = proposal_amount
-        self.proposal_blind = proposal_blind
         self.proposal_serial = proposal_serial
         self.proposal_serial = proposal_serial
+        self.proposal_token_id = proposal_token_id
+        self.proposal_blind = proposal_blind
         self.all_dao_bullas = all_dao_bullas
         self.all_dao_bullas = all_dao_bullas
         self.ec = ec
         self.ec = ec
 
 
@@ -307,8 +309,9 @@ class ProposerTxDaoProof:
             self.proposal_dest[0],
             self.proposal_dest[0],
             self.proposal_dest[1],
             self.proposal_dest[1],
             self.proposal_amount,
             self.proposal_amount,
-            self.proposal_blind,
             self.proposal_serial,
             self.proposal_serial,
+            self.proposal_token_id,
+            self.proposal_blind,
             bulla
             bulla
         )
         )
         # The merkle root
         # The merkle root
@@ -360,8 +363,7 @@ class VoteTxBuilder:
         self.inputs.append(input)
         self.inputs.append(input)
 
 
     def set_vote_option(self, vote_option):
     def set_vote_option(self, vote_option):
-        assert vote_option == 1 or vote_option == -1
-        vote_option = vote_option % self.ec.p
+        assert vote_option == 0 or vote_option == 1
         self.vote_option = vote_option
         self.vote_option = vote_option
 
 
     def build(self):
     def build(self):
@@ -387,7 +389,6 @@ class VoteTxBuilder:
                 input.note.value, input.note.token_id, value_blind,
                 input.note.value, input.note.token_id, value_blind,
                 token_blind, input.note.serial, input.note.coin_blind,
                 token_blind, input.note.serial, input.note.coin_blind,
                 input.secret, input.note.spend_hook, input.note.user_data,
                 input.secret, input.note.spend_hook, input.note.user_data,
-                self.vote_option, vote_option_blind,
                 input.all_coins, signature_secret,
                 input.all_coins, signature_secret,
                 self.ec)
                 self.ec)
             tx_input.revealed = tx_input.burn_proof.get_revealed()
             tx_input.revealed = tx_input.burn_proof.get_revealed()
@@ -396,12 +397,14 @@ class VoteTxBuilder:
         assert len(self.inputs) > 0
         assert len(self.inputs) > 0
         token_id = self.inputs[0].note.token_id
         token_id = self.inputs[0].note.token_id
 
 
+        vote_blind = self.ec.random_scalar()
+
         # This whole tx is like just burning tokens
         # This whole tx is like just burning tokens
         # except we produce an output commitment to the total value in
         # except we produce an output commitment to the total value in
         tx.vote = ClassNamespace()
         tx.vote = ClassNamespace()
         tx.vote.__name__ = "Vote"
         tx.vote.__name__ = "Vote"
         tx.vote.proof = VoteProof(total_value, token_id,
         tx.vote.proof = VoteProof(total_value, token_id,
-                                  total_blind, token_blind,
+                                  total_blind, token_blind, vote_blind,
                                   self.vote_option, vote_option_blind,
                                   self.vote_option, vote_option_blind,
                                   self.ec)
                                   self.ec)
         tx.vote.revealed = tx.vote.proof.get_revealed()
         tx.vote.revealed = tx.vote.proof.get_revealed()
@@ -415,11 +418,9 @@ class VoteTxBuilder:
         tx.note.vote_option = self.vote_option
         tx.note.vote_option = self.vote_option
         tx.note.value_blind = total_blind
         tx.note.value_blind = total_blind
         tx.note.token_blind = token_blind
         tx.note.token_blind = token_blind
+        tx.note.vote_blind = vote_blind
         tx.note.vote_option_blind = vote_option_blind
         tx.note.vote_option_blind = vote_option_blind
 
 
-        assert tx.vote.revealed.token_commit == crypto.pedersen_encrypt(
-            token_id, token_blind, self.ec)
-
         unsigned_tx_data = tx.partial_encode()
         unsigned_tx_data = tx.partial_encode()
         for (input, signature_secret) in zip(tx.inputs, signature_secrets):
         for (input, signature_secret) in zip(tx.inputs, signature_secrets):
             signature = crypto.sign(unsigned_tx_data, signature_secret, self.ec)
             signature = crypto.sign(unsigned_tx_data, signature_secret, self.ec)
@@ -429,9 +430,9 @@ class VoteTxBuilder:
 
 
 class VoteBurnProof:
 class VoteBurnProof:
 
 
-    def __init__(self, value, token_id, value_blind, token_blind, serial,
+    def __init__(self, value, token_id,
+                 value_blind, token_blind, serial,
                  coin_blind, secret, spend_hook, user_data,
                  coin_blind, secret, spend_hook, user_data,
-                 vote_option, vote_option_blind,
                  all_coins, signature_secret, ec):
                  all_coins, signature_secret, ec):
         self.value = value
         self.value = value
         self.token_id = token_id
         self.token_id = token_id
@@ -442,8 +443,6 @@ class VoteBurnProof:
         self.secret = secret
         self.secret = secret
         self.spend_hook = spend_hook
         self.spend_hook = spend_hook
         self.user_data = user_data
         self.user_data = user_data
-        self.vote_option = vote_option
-        self.vote_option_blind = vote_option_blind
         self.all_coins = all_coins
         self.all_coins = all_coins
         self.signature_secret = signature_secret
         self.signature_secret = signature_secret
 
 
@@ -453,12 +452,9 @@ class VoteBurnProof:
         revealed = ClassNamespace()
         revealed = ClassNamespace()
         revealed.nullifier = crypto.ff_hash(self.ec.p, self.secret, self.serial)
         revealed.nullifier = crypto.ff_hash(self.ec.p, self.secret, self.serial)
 
 
-        v = crypto.pedersen_encrypt(
+        revealed.value_commit = crypto.pedersen_encrypt(
             self.value, self.value_blind, self.ec
             self.value, self.value_blind, self.ec
         )
         )
-        # Multiply the point by vote_option
-        revealed.value_commit = (
-            v[0], (self.vote_option * v[1]) % self.ec.p, v[2])
 
 
         revealed.token_commit = crypto.pedersen_encrypt(
         revealed.token_commit = crypto.pedersen_encrypt(
             self.token_id, self.token_blind, self.ec
             self.token_id, self.token_blind, self.ec
@@ -470,10 +466,6 @@ class VoteBurnProof:
         revealed.signature_public = self.ec.multiply(self.signature_secret,
         revealed.signature_public = self.ec.multiply(self.signature_secret,
                                                      self.ec.G)
                                                      self.ec.G)
 
 
-        revealed.vote_option_commit = crypto.ff_hash(
-            self.ec.p, self.vote_option, self.vote_option_blind
-        )
-
         return revealed
         return revealed
 
 
     def verify(self, public):
     def verify(self, public):
@@ -501,29 +493,31 @@ class VoteBurnProof:
             revealed.token_commit == public.token_commit,
             revealed.token_commit == public.token_commit,
             revealed.all_coins == public.all_coins,
             revealed.all_coins == public.all_coins,
             revealed.signature_public == public.signature_public,
             revealed.signature_public == public.signature_public,
-            revealed.vote_option_commit == public.vote_option_commit
         ])
         ])
 
 
 class VoteProof:
 class VoteProof:
 
 
-    def __init__(self, value, token_id, value_blind, token_blind,
+    def __init__(self, value, token_id,
+                 value_blind, token_blind, vote_blind,
                  vote_option, vote_option_blind, ec):
                  vote_option, vote_option_blind, ec):
         self.value = value
         self.value = value
         self.token_id = token_id
         self.token_id = token_id
         self.value_blind = value_blind
         self.value_blind = value_blind
         self.token_blind = token_blind
         self.token_blind = token_blind
+        self.vote_blind = vote_blind
         self.vote_option = vote_option
         self.vote_option = vote_option
         self.vote_option_blind = vote_option_blind
         self.vote_option_blind = vote_option_blind
         self.ec = ec
         self.ec = ec
 
 
     def get_revealed(self):
     def get_revealed(self):
         revealed = ClassNamespace()
         revealed = ClassNamespace()
-        v = crypto.pedersen_encrypt(
+        # Multiply the point by vote_option
+        revealed.value_commit = crypto.pedersen_encrypt(
             self.value, self.value_blind, self.ec
             self.value, self.value_blind, self.ec
         )
         )
-        # Multiply the point by vote_option
-        revealed.value_commit = (
-            v[0], (self.vote_option * v[1]) % self.ec.p, v[2])
+        revealed.vote_commit = crypto.pedersen_encrypt(
+            self.vote_option * self.value, self.vote_blind, self.ec
+        )
         revealed.token_commit = crypto.pedersen_encrypt(
         revealed.token_commit = crypto.pedersen_encrypt(
             self.token_id, self.token_blind, self.ec
             self.token_id, self.token_blind, self.ec
         )
         )
@@ -534,8 +528,8 @@ class VoteProof:
 
 
     def verify(self, public):
     def verify(self, public):
         revealed = self.get_revealed()
         revealed = self.get_revealed()
-        # vote option should be -1 or 1
-        if ((self.vote_option - 1) * (self.vote_option + 1)) % self.ec.p != 0:
+        # vote option should be 0 or 1
+        if ((self.vote_option - 0) * (self.vote_option - 1)) % self.ec.p != 0:
             return False
             return False
         return all([
         return all([
             revealed.value_commit == public.value_commit,
             revealed.value_commit == public.value_commit,
@@ -559,9 +553,6 @@ class VoteTx:
         if not self._check_value_commits():
         if not self._check_value_commits():
             return False, "value commits do not match"
             return False, "value commits do not match"
 
 
-        if not self._check_vote_options():
-            return False, "value options do not match"
-
         if not self._check_proofs():
         if not self._check_proofs():
             return False, "proofs failed to verify"
             return False, "proofs failed to verify"
 
 
@@ -570,13 +561,6 @@ class VoteTx:
 
 
         return True, None
         return True, None
 
 
-    def _check_vote_options(self):
-        vote_commit = self.vote.revealed.vote_option_commit
-        for input in self.inputs:
-            if input.revealed.vote_option_commit != vote_commit:
-                return False
-        return True
-
     def _check_value_commits(self):
     def _check_value_commits(self):
         valcom_total = (0, 1, 0)
         valcom_total = (0, 1, 0)
         for input in self.inputs:
         for input in self.inputs:
@@ -675,6 +659,8 @@ class DaoState:
     def __init__(self):
     def __init__(self):
         self.dao_bullas = set()
         self.dao_bullas = set()
         self.proposals = set()
         self.proposals = set()
+        # Closed proposals
+        self.proposal_nullifiers = set()
 
 
     def is_valid_merkle(self, all_dao_bullas):
     def is_valid_merkle(self, all_dao_bullas):
         return all_dao_bullas.issubset(self.dao_bullas)
         return all_dao_bullas.issubset(self.dao_bullas)
@@ -682,6 +668,9 @@ class DaoState:
     def apply_proposal_tx(self, update):
     def apply_proposal_tx(self, update):
         self.proposals.add(update.proposal)
         self.proposals.add(update.proposal)
 
 
+    def apply_exec_tx(self, update):
+        pass
+
     def apply(self, update):
     def apply(self, update):
         self.dao_bullas.add(update.bulla)
         self.dao_bullas.add(update.bulla)
 
 
@@ -700,7 +689,11 @@ def dao_state_transition(state, tx):
 
 
 class DaoExecBuilder:
 class DaoExecBuilder:
 
 
-    def __init__(self):
+    def __init__(self,
+        proposal,
+        all_proposals,
+        dao
+    ):
         pass
         pass
 
 
     def build(self):
     def build(self):
@@ -919,6 +912,21 @@ def main(argv):
         # Try decrypt note here
         # Try decrypt note here
         print(f"Received {enc_note.value} GOV")
         print(f"Received {enc_note.value} GOV")
 
 
+    ################################################
+    # DAO rules:
+    # 1. gov token IDs must match on all inputs
+    # 2. proposals must be submitted by minimum amount
+    #       - need protection so can't collude? must be a single signer??
+    #         - stellar: doesn't have to be robust for this MVP
+    # 3. number of votes >= quorum
+    #       - just positive votes or all votes?
+    #         - stellar: no that's all votes
+    # 4. outcome > approval_ratio
+    # 5. structure of outputs
+    #   output 0: value and address
+    #   output 1: change address
+    ################################################
+
     ################################################
     ################################################
     # Propose the vote
     # Propose the vote
     # In order to make a valid vote, first the proposer must
     # In order to make a valid vote, first the proposer must
@@ -935,9 +943,10 @@ def main(argv):
     proposal = ClassNamespace()
     proposal = ClassNamespace()
     proposal.dest = user_public
     proposal.dest = user_public
     proposal.amount = 1000
     proposal.amount = 1000
-    proposal.blind = ec.random_base()
     # Used to produce the nullifier when the vote is executed
     # Used to produce the nullifier when the vote is executed
     proposal.serial = ec.random_base()
     proposal.serial = ec.random_base()
+    proposal.token_id = money_token_id
+    proposal.blind = ec.random_base()
 
 
     # For vote to become valid, the proposer must prove
     # For vote to become valid, the proposer must prove
     # that they own more than proposer_limit number of gov tokens.
     # that they own more than proposer_limit number of gov tokens.
@@ -985,7 +994,7 @@ def main(argv):
     # User 2: NO
     # User 2: NO
     builder = VoteTxBuilder(ec)
     builder = VoteTxBuilder(ec)
     builder.add_input(witness, gov_secret_2, gov_user_2_note)
     builder.add_input(witness, gov_secret_2, gov_user_2_note)
-    builder.set_vote_option(-1)
+    builder.set_vote_option(0)
     tx2 = builder.build()
     tx2 = builder.build()
 
 
     if (update := vote_state_transition(vote_state, gov_state, tx2)) is None:
     if (update := vote_state_transition(vote_state, gov_state, tx2)) is None:
@@ -1025,6 +1034,10 @@ def main(argv):
 
 
     win_votes = 0
     win_votes = 0
     total_votes = 0
     total_votes = 0
+    total_vote_blinds = 0
+    total_value_blinds = 0
+    total_value_commit = (0, 1, 0)
+    total_vote_commit = (0, 1, 0)
     for i, (note, tx) in enumerate(
     for i, (note, tx) in enumerate(
         zip([note_vote_1, note_vote_2, note_vote_3], [tx1, tx2, tx3])):
         zip([note_vote_1, note_vote_2, note_vote_3], [tx1, tx2, tx3])):
 
 
@@ -1037,18 +1050,24 @@ def main(argv):
             ec.p, note.vote_option, note.vote_option_blind)
             ec.p, note.vote_option, note.vote_option_blind)
         assert tx.vote.revealed.vote_option_commit == vote_option_commit
         assert tx.vote.revealed.vote_option_commit == vote_option_commit
 
 
-        v = crypto.pedersen_encrypt(
+        value_commit = crypto.pedersen_encrypt(
             note.value, note.value_blind, ec)
             note.value, note.value_blind, ec)
-        value_commit = (v[0], (note.vote_option * v[1]) % ec.p, v[2])
         assert tx.vote.revealed.value_commit == value_commit
         assert tx.vote.revealed.value_commit == value_commit
+        total_value_commit = ec.add(total_value_commit, value_commit)
+        total_value_blinds += note.value_blind
+        
+        vote_commit = crypto.pedersen_encrypt(
+            note.vote_option * note.value, note.vote_blind, ec)
+        assert tx.vote.revealed.vote_commit == vote_commit
+        total_vote_commit = ec.add(total_vote_commit, vote_commit)
+        total_vote_blinds += note.vote_blind
 
 
         vote_option = note.vote_option
         vote_option = note.vote_option
-        if vote_option > 2**64:
-            vote_option = -(ec.p - vote_option)
-        assert vote_option == 1 or vote_option == -1
+        assert vote_option == 0 or vote_option == 1
 
 
         if vote_option == 1:
         if vote_option == 1:
             win_votes += note.value
             win_votes += note.value
+
         total_votes += note.value
         total_votes += note.value
 
 
         if vote_option == 1:
         if vote_option == 1:
@@ -1059,6 +1078,13 @@ def main(argv):
 
 
     print(f"Outcome = {win_votes} / {total_votes}")
     print(f"Outcome = {win_votes} / {total_votes}")
 
 
+    total_value_commit2 = crypto.pedersen_encrypt(
+        total_votes, total_value_blinds, ec)
+    assert total_value_commit == total_value_commit2
+    total_vote_commit2 = crypto.pedersen_encrypt(
+        win_votes, total_vote_blinds, ec)
+    assert total_vote_commit == total_vote_commit2
+
     ################################################
     ################################################
     # Execute the vote
     # Execute the vote
     ################################################
     ################################################
@@ -1107,25 +1133,45 @@ def main(argv):
         dao_bulla_blind
         dao_bulla_blind
     ) # DAO bulla
     ) # DAO bulla
 
 
-    # proposer proof
-
-    # Now enforce DAO rules:
-    # 1. gov token IDs must match on all inputs
-    # 2. proposals must be submitted by minimum amount
-    #       - need protection so can't collude? must be a single signer??
-    #         - stellar: doesn't have to be robust for this MVP
-    # 4. number of votes >= quorum
-    #       - just positive votes or all votes?
-    #         - stellar: no that's all votes
-    # 4. outcome > approval_ratio
-    # 5. structure of outputs
+    # execution proof
+    # 1. total votes >= quorum
+    # 2. win_votes / total_votes >= approval_ratio
+    # 3. structure of outputs
     #   output 0: value and address
     #   output 0: value and address
     #   output 1: change address
     #   output 1: change address
-    builder = DaoExecBuilder()
+
+    # - check proposal exists
+    # - create proposal nullifier
+    #     - verifier: check it doesn't already exist
+    # - check dest, amount, token_id match
+    #     - export both output value_commits
+    #     - export token_id commit used in send_payment tx
+    #     - export output 0 and 1 dest
+    #     - check all these fields match the tx
+    # - is linked to DAO
+    #     - read DAO params
+    #     - re-export as enc_user_data
+    #     - verifier: check it matches the tx
+    # - total_votes >= quorum
+    #     - verifier: check sum of vote_commits is correct
+    # - win_votes / total_votes >= approval_ratio
+
+    dao = ClassNamespace()
+    dao.proposer_limit = dao_proposer_limit
+    dao.quorum = dao_quorum
+    dao.approval_ratio = dao_approval_ratio
+    dao.gov_token_id = gov_token_id
+    dao.bulla_blind = dao_bulla_blind
+
+    builder = DaoExecBuilder(
+        proposal,
+        dao_state.proposals,
+        dao,
+    )
     tx = builder.build()
     tx = builder.build()
     if (update := dao_exec_state_transition(dao_state, tx)) is None:
     if (update := dao_exec_state_transition(dao_state, tx)) is None:
         return -1
         return -1
-    #dao_state.apply_exec(update)
+    dao_state.apply_exec_tx(update)
 
 
     return 0
     return 0
 
 

+ 6 - 1
bin/daod/demo/money.py

@@ -317,6 +317,10 @@ class MintProof:
             self.token_id, self.token_blind, self.ec
             self.token_id, self.token_blind, self.ec
         )
         )
 
 
+        revealed.dest_commit = ff_hash(
+            self.ec.p, self.public[0], self.public[1]
+        )
+
         return revealed
         return revealed
 
 
     def verify(self, public):
     def verify(self, public):
@@ -324,6 +328,7 @@ class MintProof:
         return all([
         return all([
             revealed.coin == public.coin,
             revealed.coin == public.coin,
             revealed.value_commit == public.value_commit,
             revealed.value_commit == public.value_commit,
-            revealed.token_commit == public.token_commit
+            revealed.token_commit == public.token_commit,
+            revealed.dest_commit == public.dest_commit
         ])
         ])