Explorar o código

switch DAO auth enc to use ElGamalEncryptedNote from SDK

zero %!s(int64=2) %!d(string=hai) anos
pai
achega
56cc2b1627

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

@@ -455,10 +455,6 @@ This provides verifiable note encryption for all output coins in the sibling `Mo
 {{#include ../../../../../src/contract/dao/src/model.rs:dao-auth_xfer-params}}
 ```
 
-```rust
-{{#include ../../../../../src/contract/dao/src/model.rs:dao-auth_coinattrs-params}}
-```
-
 ### Contract Statement
 
 Denote the DAO contract ID by $\t{CID}_\t{DAO} ∈ 𝔽ₚ$.

+ 11 - 9
src/contract/dao/proof/dao-auth-money-transfer-enc-coin.zk

@@ -56,29 +56,31 @@ circuit "DaoAuthMoneyTransferEncCoin" {
     const_2 = witness_base(2);
     const_3 = witness_base(3);
     const_4 = witness_base(4);
+    const_5 = witness_base(5);
 
     # Each blinding value must be used only once otherwise they
     # could be calculated.
 
     # We can skip the public_key since it's inferred by the receiver
 
-    enc_value = base_add(value, shared_secret);
+    shared_secret_1 = poseidon_hash(shared_secret, const_1);
+    enc_value = base_add(value, shared_secret_1);
     constrain_instance(enc_value);
 
-    shared_secret_1 = poseidon_hash(shared_secret, const_1);
-    enc_token_id = base_add(token_id, shared_secret_1);
+    shared_secret_2 = poseidon_hash(shared_secret, const_2);
+    enc_token_id = base_add(token_id, shared_secret_2);
     constrain_instance(enc_token_id);
 
-    shared_secret_2 = poseidon_hash(shared_secret, const_2);
-    enc_serial = base_add(serial, shared_secret_2);
+    shared_secret_3 = poseidon_hash(shared_secret, const_3);
+    enc_serial = base_add(serial, shared_secret_3);
     constrain_instance(enc_serial);
 
-    shared_secret_3 = poseidon_hash(shared_secret, const_3);
-    enc_spend_hook = base_add(spend_hook, shared_secret_3);
+    shared_secret_4 = poseidon_hash(shared_secret, const_4);
+    enc_spend_hook = base_add(spend_hook, shared_secret_4);
     constrain_instance(enc_spend_hook);
 
-    shared_secret_4 = poseidon_hash(shared_secret, const_4);
-    enc_user_data = base_add(user_data, shared_secret_4);
+    shared_secret_5 = poseidon_hash(shared_secret, const_5);
+    enc_user_data = base_add(user_data, shared_secret_5);
     constrain_instance(enc_user_data);
 }
 

+ 7 - 5
src/contract/dao/proof/dao-auth-money-transfer.zk

@@ -112,19 +112,21 @@ circuit "DaoAuthMoneyTransfer" {
 
     const_1 = witness_base(1);
     const_2 = witness_base(2);
+    const_3 = witness_base(3);
 
     # Value
-    enc_value = base_add(dao_value, shared_secret);
+    shared_secret_1 = poseidon_hash(shared_secret, const_1);
+    enc_value = base_add(dao_value, shared_secret_1);
     constrain_instance(enc_value);
 
     # Token ID
-    shared_secret_1 = poseidon_hash(shared_secret, const_1);
-    enc_token_id = base_add(dao_token_id, shared_secret_1);
+    shared_secret_2 = poseidon_hash(shared_secret, const_2);
+    enc_token_id = base_add(dao_token_id, shared_secret_2);
     constrain_instance(enc_token_id);
 
     # Serial
-    shared_secret_2 = poseidon_hash(shared_secret, const_2);
-    enc_serial = base_add(dao_serial, shared_secret_2);
+    shared_secret_3 = poseidon_hash(shared_secret, const_3);
+    enc_serial = base_add(dao_serial, shared_secret_3);
     constrain_instance(enc_serial);
 }
 

+ 33 - 61
src/contract/dao/src/client/auth_xfer.rs

@@ -18,7 +18,7 @@
 
 use darkfi_money_contract::model::CoinAttributes;
 use darkfi_sdk::{
-    crypto::{pasta_prelude::*, poseidon_hash, util::mod_r_p, PublicKey, DAO_CONTRACT_ID},
+    crypto::{note::ElGamalEncryptedNote, poseidon_hash, PublicKey, SecretKey, DAO_CONTRACT_ID},
     pasta::pallas,
 };
 
@@ -30,9 +30,7 @@ use darkfi::{
     Result,
 };
 
-use crate::model::{
-    Dao, DaoAuthCoinAttrs, DaoAuthMoneyTransferParams, DaoProposal, VecAuthCallCommit,
-};
+use crate::model::{Dao, DaoAuthMoneyTransferParams, DaoProposal, VecAuthCallCommit};
 
 pub struct DaoAuthMoneyTransferCall {
     pub proposal: DaoProposal,
@@ -60,48 +58,41 @@ impl DaoAuthMoneyTransferCall {
         for coin_attrs in proposal_coinattrs {
             let coin = coin_attrs.to_coin();
 
-            let ephem_secret = pallas::Base::random(&mut OsRng);
-            let ephem_pubkey = PublicKey::from_secret(ephem_secret.into());
+            let ephem_secret = SecretKey::random(&mut OsRng);
+            let ephem_pubkey = PublicKey::from_secret(ephem_secret);
             let (ephem_x, ephem_y) = ephem_pubkey.xy();
 
-            let public_key = coin_attrs.public_key.inner();
             let value_base = pallas::Base::from(coin_attrs.value);
 
-            let shared_point = public_key * mod_r_p(ephem_secret);
-            let shared_point_coords = shared_point.to_affine().coordinates().unwrap();
-            let (shared_point_x, shared_point_y) =
-                (*shared_point_coords.x(), *shared_point_coords.y());
-            let shared_secret = poseidon_hash([shared_point_x, shared_point_y]);
-            let enc_value = value_base + shared_secret;
-
-            let enc_token_id =
-                coin_attrs.token_id.inner() + poseidon_hash([shared_secret, pallas::Base::from(1)]);
-            let enc_serial =
-                coin_attrs.serial + poseidon_hash([shared_secret, pallas::Base::from(2)]);
-            let enc_spend_hook =
-                coin_attrs.spend_hook + poseidon_hash([shared_secret, pallas::Base::from(3)]);
-            let enc_user_data =
-                coin_attrs.user_data + poseidon_hash([shared_secret, pallas::Base::from(4)]);
+            let note = [
+                value_base,
+                coin_attrs.token_id.inner(),
+                coin_attrs.serial,
+                coin_attrs.spend_hook,
+                coin_attrs.user_data,
+            ];
+            let enc_note =
+                ElGamalEncryptedNote::encrypt(note, &ephem_secret, &coin_attrs.public_key);
 
             let prover_witnesses = vec![
-                Witness::EcNiPoint(Value::known(public_key)),
+                Witness::EcNiPoint(Value::known(coin_attrs.public_key.inner())),
                 Witness::Base(Value::known(value_base)),
                 Witness::Base(Value::known(coin_attrs.token_id.inner())),
                 Witness::Base(Value::known(coin_attrs.serial)),
                 Witness::Base(Value::known(coin_attrs.spend_hook)),
                 Witness::Base(Value::known(coin_attrs.user_data)),
-                Witness::Base(Value::known(ephem_secret)),
+                Witness::Base(Value::known(ephem_secret.inner())),
             ];
 
             let public_inputs = vec![
                 coin.inner(),
                 ephem_x,
                 ephem_y,
-                enc_value,
-                enc_token_id,
-                enc_serial,
-                enc_spend_hook,
-                enc_user_data,
+                enc_note.encrypted_values[0],
+                enc_note.encrypted_values[1],
+                enc_note.encrypted_values[2],
+                enc_note.encrypted_values[3],
+                enc_note.encrypted_values[4],
             ];
 
             let circuit = ZkCircuit::new(prover_witnesses, auth_xfer_enc_coin_zkbin);
@@ -110,43 +101,24 @@ impl DaoAuthMoneyTransferCall {
                     .expect("DAO::exec() proving error!)");
             proofs.push(proof);
 
-            enc_attrs.push(DaoAuthCoinAttrs {
-                value: enc_value,
-                token_id: enc_token_id,
-                serial: enc_serial,
-                spend_hook: enc_spend_hook,
-                user_data: enc_user_data,
-                ephem_pubkey,
-            });
+            enc_attrs.push(enc_note);
         }
 
         // Build the main proof
 
-        let ephem_secret = pallas::Base::random(&mut OsRng);
-        let change_ephem_pubkey = PublicKey::from_secret(ephem_secret.into());
+        let ephem_secret = SecretKey::random(&mut OsRng);
+        let change_ephem_pubkey = PublicKey::from_secret(ephem_secret);
         let (ephem_x, ephem_y) = change_ephem_pubkey.xy();
 
         let dao_public_key = self.dao.public_key.inner();
         let dao_change_value = pallas::Base::from(self.dao_coin_attrs.value);
 
-        let shared_point = dao_public_key * mod_r_p(ephem_secret);
-        let shared_point_coords = shared_point.to_affine().coordinates().unwrap();
-        let (shared_point_x, shared_point_y) = (*shared_point_coords.x(), *shared_point_coords.y());
-        let shared_secret = poseidon_hash([shared_point_x, shared_point_y]);
-        let change_enc_value = dao_change_value + shared_secret;
-
-        let change_enc_token_id = self.dao_coin_attrs.token_id.inner() +
-            poseidon_hash([shared_secret, pallas::Base::from(1)]);
-        let change_enc_serial =
-            self.dao_coin_attrs.serial + poseidon_hash([shared_secret, pallas::Base::from(2)]);
-
-        let params = DaoAuthMoneyTransferParams {
-            enc_attrs,
-            change_enc_value,
-            change_enc_token_id,
-            change_enc_serial,
-            change_ephem_pubkey,
-        };
+        let note =
+            [dao_change_value, self.dao_coin_attrs.token_id.inner(), self.dao_coin_attrs.serial];
+        let dao_change_attrs =
+            ElGamalEncryptedNote::encrypt(note, &ephem_secret, &self.dao.public_key);
+
+        let params = DaoAuthMoneyTransferParams { enc_attrs, dao_change_attrs };
 
         let dao_proposer_limit = pallas::Base::from(self.dao.proposer_limit);
         let dao_quorum = pallas::Base::from(self.dao.quorum);
@@ -180,7 +152,7 @@ impl DaoAuthMoneyTransferCall {
             // DAO_CONTRACT_ID
             Witness::Base(Value::known(DAO_CONTRACT_ID.inner())),
             // Encrypted change DAO output
-            Witness::Base(Value::known(ephem_secret)),
+            Witness::Base(Value::known(ephem_secret.inner())),
         ];
 
         let public_inputs = vec![
@@ -191,9 +163,9 @@ impl DaoAuthMoneyTransferCall {
             self.proposal.auth_calls.commit(),
             ephem_x,
             ephem_y,
-            change_enc_value,
-            change_enc_token_id,
-            change_enc_serial,
+            dao_change_attrs.encrypted_values[0],
+            dao_change_attrs.encrypted_values[1],
+            dao_change_attrs.encrypted_values[2],
         ];
 
         let circuit = ZkCircuit::new(prover_witnesses, auth_xfer_zkbin);

+ 11 - 11
src/contract/dao/src/entrypoint/auth_xfer.rs

@@ -60,20 +60,20 @@ pub(crate) fn dao_authxfer_get_metadata(
     let mut zk_public_inputs: Vec<(String, Vec<pallas::Base>)> = vec![];
     let signature_pubkeys: Vec<PublicKey> = vec![];
 
-    for (output, attrs) in xfer_params.outputs.iter().zip(self_params.enc_attrs.iter()) {
+    for (output, enc_attrs) in xfer_params.outputs.iter().zip(self_params.enc_attrs.iter()) {
         let coin = output.coin;
-        let (ephem_x, ephem_y) = attrs.ephem_pubkey.xy();
+        let (ephem_x, ephem_y) = enc_attrs.ephem_public.xy();
         zk_public_inputs.push((
             DAO_CONTRACT_ZKAS_DAO_AUTH_MONEY_TRANSFER_ENC_COIN_NS.to_string(),
             vec![
                 coin.inner(),
                 ephem_x,
                 ephem_y,
-                attrs.value,
-                attrs.token_id,
-                attrs.serial,
-                attrs.spend_hook,
-                attrs.user_data,
+                enc_attrs.encrypted_values[0],
+                enc_attrs.encrypted_values[1],
+                enc_attrs.encrypted_values[2],
+                enc_attrs.encrypted_values[3],
+                enc_attrs.encrypted_values[4],
             ],
         ));
     }
@@ -84,7 +84,7 @@ pub(crate) fn dao_authxfer_get_metadata(
     // Also check the coin in the change output
     let last_coin = xfer_params.outputs.last().unwrap().coin;
 
-    let (ephem_x, ephem_y) = self_params.change_ephem_pubkey.xy();
+    let (ephem_x, ephem_y) = self_params.dao_change_attrs.ephem_public.xy();
     zk_public_inputs.push((
         DAO_CONTRACT_ZKAS_DAO_AUTH_MONEY_TRANSFER_NS.to_string(),
         vec![
@@ -95,9 +95,9 @@ pub(crate) fn dao_authxfer_get_metadata(
             exec_params.proposal_auth_calls.commit(),
             ephem_x,
             ephem_y,
-            self_params.change_enc_value,
-            self_params.change_enc_token_id,
-            self_params.change_enc_serial,
+            self_params.dao_change_attrs.encrypted_values[0],
+            self_params.dao_change_attrs.encrypted_values[1],
+            self_params.dao_change_attrs.encrypted_values[2],
         ],
     ));
 

+ 2 - 19
src/contract/dao/src/model.rs

@@ -364,24 +364,7 @@ pub struct DaoExecUpdate {
 // ANCHOR: dao-auth_xfer-params
 /// Parameters for `Dao::AuthMoneyTransfer`
 pub struct DaoAuthMoneyTransferParams {
-    pub enc_attrs: Vec<DaoAuthCoinAttrs>,
-
-    pub change_ephem_pubkey: PublicKey,
-    pub change_enc_value: pallas::Base,
-    pub change_enc_token_id: pallas::Base,
-    pub change_enc_serial: pallas::Base,
+    pub enc_attrs: Vec<ElGamalEncryptedNote<5>>,
+    pub dao_change_attrs: ElGamalEncryptedNote<3>,
 }
 // ANCHOR_END: dao-auth_xfer-params
-
-#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
-// ANCHOR: dao-auth_coinattrs-params
-pub struct DaoAuthCoinAttrs {
-    pub ephem_pubkey: PublicKey,
-
-    pub value: pallas::Base,
-    pub token_id: pallas::Base,
-    pub serial: pallas::Base,
-    pub spend_hook: pallas::Base,
-    pub user_data: pallas::Base,
-}
-// ANCHOR_END: dao-auth_coinattrs-params

+ 2 - 2
src/contract/test-harness/src/vks.rs

@@ -50,8 +50,8 @@ use darkfi_serial::{deserialize, serialize};
 use log::debug;
 
 /// Update this if any circuits are changed
-const VKS_HASH: &str = "81036e85adea1b407698b0a3f58020f69ed6ac6c7843243b8b7b026d165f237f";
-const PKS_HASH: &str = "40c0c448274dfe66ec4249a38e69b1c2f7fd971cc3d35fbb2129f4ee8ee8aea5";
+const VKS_HASH: &str = "191e742f12fe776f76f9cda4e72ac3a4f92cd3873f2ea04e3887ac54d7ca5340";
+const PKS_HASH: &str = "da22afe484b762c6308241c91fe4d399f11b15f62e493c5fef4dea53f72976c1";
 
 fn pks_path(typ: &str) -> Result<PathBuf> {
     let output = Command::new("git").arg("rev-parse").arg("--show-toplevel").output()?.stdout;