switch DAO auth enc to use ElGamalEncryptedNote from SDK

This commit is contained in:
zero
2024-01-23 10:56:08 +01:00
parent 63619cf061
commit 56cc2b1627
7 changed files with 65 additions and 110 deletions

View File

@@ -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} ∈ 𝔽ₚ$.

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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],
],
));

View File

@@ -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

View File

@@ -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;