diff --git a/doc/src/spec/contract/dao/scheme.md b/doc/src/spec/contract/dao/scheme.md index ce776dc7b..93e701242 100644 --- a/doc/src/spec/contract/dao/scheme.md +++ b/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} ∈ 𝔽ₚ$. diff --git a/src/contract/dao/proof/dao-auth-money-transfer-enc-coin.zk b/src/contract/dao/proof/dao-auth-money-transfer-enc-coin.zk index 2f2564ba8..ad69e2d56 100644 --- a/src/contract/dao/proof/dao-auth-money-transfer-enc-coin.zk +++ b/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); } diff --git a/src/contract/dao/proof/dao-auth-money-transfer.zk b/src/contract/dao/proof/dao-auth-money-transfer.zk index 20ca5e42f..b9f70c334 100644 --- a/src/contract/dao/proof/dao-auth-money-transfer.zk +++ b/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); } diff --git a/src/contract/dao/src/client/auth_xfer.rs b/src/contract/dao/src/client/auth_xfer.rs index cd07c3b0b..71b0c069a 100644 --- a/src/contract/dao/src/client/auth_xfer.rs +++ b/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 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 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 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); diff --git a/src/contract/dao/src/entrypoint/auth_xfer.rs b/src/contract/dao/src/entrypoint/auth_xfer.rs index 8f937bcce..5d314b7a9 100644 --- a/src/contract/dao/src/entrypoint/auth_xfer.rs +++ b/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)> = vec![]; let signature_pubkeys: Vec = 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], ], )); diff --git a/src/contract/dao/src/model.rs b/src/contract/dao/src/model.rs index 92bc01cf3..0ec7618db 100644 --- a/src/contract/dao/src/model.rs +++ b/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, - - 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>, + 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 diff --git a/src/contract/test-harness/src/vks.rs b/src/contract/test-harness/src/vks.rs index 235fe7821..bd2b6e716 100644 --- a/src/contract/test-harness/src/vks.rs +++ b/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 { let output = Command::new("git").arg("rev-parse").arg("--show-toplevel").output()?.stdout;