zero 2 лет назад
Родитель
Сommit
75484eb7e4
3 измененных файлов с 122 добавлено и 16 удалено
  1. 105 4
      doc/src/spec/contract/dao/scheme.md
  2. 1 4
      src/contract/dao/proof/dao-exec.zk
  3. 16 8
      src/contract/dao/src/model.rs

+ 105 - 4
doc/src/spec/contract/dao/scheme.md

@@ -123,7 +123,7 @@ Let the total funds $v = ∑_{i ∈ 𝐢} i.v$, then check $d.L ≤ v$.
 $V = ∑_{i ∈ 𝐢} i.V$. We use this to check that $v = ∑_{i ∈ 𝐢} i.v$ as
 claimed in the *proposer limit threshold met* check.
 
-For each input $i ∈ 𝐢$,
+For each input $i ∈ 𝐢$, perform the following checks:
 
   **Unused nullifier**   check that $\cN$ does not exist in the
 money contract nullifiers DB.
@@ -160,7 +160,7 @@ Define the DAO vote function params
 $$ \begin{aligned}
   τ &∈ 𝔽ₚ \\
   𝒫 &∈ \t{im}(\t{Bulla}_\t{Proposal}) \\
-  Y &∈ ℙₚ \\
+  V_\t{yes} &∈ ℙₚ \\
   \t{EncNote} &∈ ⟂ \\
   𝐢 &∈ \t{VoteInput}^*
 \end{aligned} $$
@@ -208,7 +208,7 @@ commit $T = \t{PedersenCommit}(d.τ, b_τ)$ where $T = ∑_{i ∈ 𝐢} Tᵢ$.
 
 **Proposal bulla integrity**   $𝒫 = \t{Bulla}_\t{Proposal}(p, b_p)$
 
-**Yes vote commit**   $Y = \t{PedersenCommit}(ov, b_y)$
+**Yes vote commit**   $V_\t{yes} = \t{PedersenCommit}(ov, b_y)$
 
 **Total vote value commit**   $V = \t{PedersenCommit}(v, bᵥ)$ where
 $V = ∑_{i ∈ 𝐢} i.V$ should also hold.
@@ -218,7 +218,7 @@ $V = ∑_{i ∈ 𝐢} i.V$ should also hold.
 **Proposal not expired**   let $t_\t{end} = ℕ₆₄2𝔽ₚ(p.t₀) + ℕ₆₄2𝔽ₚ(p.D)$,
 and then check $t_\t{now} < t_\t{end}$.
 
-For each input $i ∈ 𝐢$,
+For each input $i ∈ 𝐢$, perform the following checks:
 
 &emsp; **Valid input merkle root** &emsp; check that $i.R_\t{coin}$ is the
 previously seen merkle root in the proposal snapshot merkle root.
@@ -250,3 +250,104 @@ Attach a proof $πᵢ$ such that the following relations hold:
 
 &emsp; **Proof of signature public key ownership** &emsp; $i.\t{PK}_σ = \t{DerivePubKey}(x_σ)$.
 
+## Exec
+
+### Function Params
+
+Let $\t{AuthCall}, \t{Commit}_{\t{Auth}^*}$ be defined as in the section [Auth Calls](model.md#auth-calls).
+
+Define the DAO exec function params
+$$ \begin{aligned}
+  𝒫 &∈ \t{im}(\t{Bulla}_\t{Proposal}) \\
+  𝒜  &∈ \t{AuthCall}^* \\
+  V_\t{yes} &∈ ℙₚ \\
+  V_\t{all} &∈ ℙₚ \\
+\end{aligned} $$
+
+```rust
+{{#include ../../../../../src/contract/dao/src/model.rs:dao-exec-params}}
+```
+
+```rust
+{{#include ../../../../../src/contract/dao/src/model.rs:dao-blind-aggregate-vote}}
+```
+
+### Contract Statement
+
+There are two phases to Exec. In the first we check the calling format of this
+transaction matches what is specified in the proposal. Then in the second phase,
+we verify the correct voting rules.
+
+**Auth call spec match** &emsp; denote the child calls of Exec by $C$.
+If $\#C ≠ \#𝒜 $ then exit.
+Otherwise, for each $c ∈ C$ and $a ∈ 𝒜 $, check the function ID of $c$ is $a$.
+
+**Aggregate votes lookup** &emsp; using the proposal bulla, fetch the
+aggregated votes from the DB and verify $V_y$ and $V_a$ are set correctly.
+
+Let there be prover auxiliary witness inputs:
+$$ \begin{aligned}
+  p &∈ \t{Params}_\t{Proposal} \\
+  b_p &∈ 𝔽ₚ \\
+  d &∈ \t{Params}_\t{DAO} \\
+  b_d &∈ 𝔽ₚ \\
+  v_y &∈ 𝔽ₚ \\
+  v_a &∈ 𝔽ₚ \\
+  b_y &∈ 𝔽ᵥ \\
+  b_a &∈ 𝔽ᵥ \\
+\end{aligned} $$
+Attach a proof $π$ such that the following relations hold:
+
+**DAO bulla integrity** &emsp; $𝒟 = \t{Bulla}_\t{DAO}(d, b_d)$
+
+**Proposal bulla integrity** &emsp; $𝒫 = \t{Bulla}_\t{Proposal}(p, b_p)$
+where $p.𝒜  = 𝒜 $.
+
+**Yes vote commit** &emsp; $V_\t{yes} = \t{PedersenCommit}(v_y, b_y)$
+
+**All vote commit** &emsp; $V_\t{yes} = \t{PedersenCommit}(v_a, b_a)$
+
+**All votes pass quorum** &emsp; $Q ≤ v_a$
+
+**Approval ratio satisfied** &emsp; we wish to check that
+$\frac{A^\%_q}{A^\%_b} ≤ \frac{v_y}{v_a}$. Instead we perform the
+equivalent check that $v_a A^\%_q ≤ v_y A^\%_b$.
+
+## AuthMoneyTransfer
+
+This is a child call for Exec which can be used for DAO treasuries.
+It checks the next sibling call is `Money::transfer()` and accordingly
+verifies the first $n - 1$ output coins match the data set in this
+call's auth data.
+
+Additionally we provide a note with the coin params that are verifiably
+encrypted to mitigate the attack where Exec is called, but the supplied
+`Money::transfer()` call contains an invalid note which cannot be
+decrypted by the receiver. In this case, the money would still leave the
+DAO treasury but be unspendable.
+
+### Function Params
+
+Define the DAO AuthMoneyTransfer function params
+$$ 𝒞_\t{enc} ∈ \t{AuthCoinAttrs}^* $$
+
+Define the DAO $\t{AuthCoinAttrs}$ as
+$$ \begin{aligned}
+  \t{AuthCoinAttrs}.v &∈ 𝔽ₚ \\
+  \t{AuthCoinAttrs}.τ &∈ 𝔽ₚ \\
+  \t{AuthCoinAttrs}.ζ &∈ 𝔽ₚ \\
+  \t{AuthCoinAttrs}.\t{SH} &∈ 𝔽ₚ \\
+  \t{AuthCoinAttrs}.\t{UD} &∈ 𝔽ₚ \\
+  \t{AuthCoinAttrs}.\t{EPK} &∈ ℙₚ
+\end{aligned} $$
+which corresponds to encrypted coin attributes. This provides verifiable
+note encryption for all output coins in the sibling `Money::transfer()` call.
+
+```rust
+{{#include ../../../../../src/contract/dao/src/model.rs:dao-auth_xfer-params}}
+```
+
+```rust
+{{#include ../../../../../src/contract/dao/src/model.rs:dao-auth_coinattrs-params}}
+```
+

+ 1 - 4
src/contract/dao/proof/dao-exec.zk

@@ -85,8 +85,5 @@ circuit "DaoExec" {
     rhs = base_mul(yes_vote_value, dao_approval_ratio_base);
     rhs_1 = base_add(rhs, one);
     less_than_strict(lhs, rhs_1);
-
-    # NOTE: There is a vulnerability here where someone can create the exec
-    # transaction with a bad note so it cannot be decrypted by the receiver
-    # TODO: Research verifiable encryption inside ZK
 }
+

+ 16 - 8
src/contract/dao/src/model.rs

@@ -312,15 +312,17 @@ pub struct DaoVoteUpdate {
     pub vote_nullifiers: Vec<Nullifier>,
 }
 
+#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
+// ANCHOR: dao-blind-aggregate-vote
 /// Represents a single or multiple blinded votes.
 /// These can be summed together.
-#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
 pub struct DaoBlindAggregateVote {
     /// Weighted vote commit
     pub yes_vote_commit: pallas::Point,
     /// All value staked in the vote
     pub all_vote_commit: pallas::Point,
 }
+// ANCHOR_END: dao-blind-aggregate-vote
 
 impl DaoBlindAggregateVote {
     /// Aggregate a vote with existing one
@@ -339,8 +341,9 @@ impl Default for DaoBlindAggregateVote {
     }
 }
 
-/// Parameters for `Dao::Exec`
 #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
+// ANCHOR: dao-exec-params
+/// Parameters for `Dao::Exec`
 pub struct DaoExecParams {
     /// The proposal bulla
     pub proposal_bulla: DaoProposalBulla,
@@ -348,6 +351,7 @@ pub struct DaoExecParams {
     /// Aggregated blinds for the vote commitments
     pub blind_total_vote: DaoBlindAggregateVote,
 }
+// ANCHOR_END: dao-exec-params
 
 /// State update for `Dao::Exec`
 #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
@@ -357,6 +361,15 @@ pub struct DaoExecUpdate {
 }
 
 #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
+// ANCHOR: dao-auth_xfer-params
+/// Parameters for `Dao::AuthMoneyTransfer`
+pub struct DaoAuthMoneyTransferParams {
+    pub enc_attrs: Vec<DaoAuthCoinAttrs>,
+}
+// ANCHOR_END: dao-auth_xfer-params
+
+#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
+// ANCHOR: dao-auth_coinattrs-params
 pub struct DaoAuthCoinAttrs {
     pub value: pallas::Base,
     pub token_id: pallas::Base,
@@ -366,9 +379,4 @@ pub struct DaoAuthCoinAttrs {
 
     pub ephem_pubkey: PublicKey,
 }
-
-/// Parameters for `Dao::AuthMoneyTransfer`
-#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
-pub struct DaoAuthMoneyTransferParams {
-    pub enc_attrs: Vec<DaoAuthCoinAttrs>,
-}
+// ANCHOR_END: dao-auth_coinattrs-params