dao: apply same verifiable encryption for other outputs, to the DAO change output as well.

This commit is contained in:
zero
2024-01-19 11:54:25 +01:00
parent 5aad1deb73
commit b1da730489
6 changed files with 95 additions and 16 deletions

View File

@@ -21,11 +21,10 @@ witness "DaoAuthMoneyTransferEncCoin" {
}
circuit "DaoAuthMoneyTransferEncCoin" {
# UGLY HACK -----------------
# cast to EcPoint
# (otherwise zkas refuses to compile)
ONE = witness_base(1);
pubkey = ec_mul_var_base(ONE, public_key);
# ---------------------------
coin = poseidon_hash(
ec_get_x(pubkey),

View File

@@ -4,6 +4,7 @@ field = "pallas";
constant "DaoAuthMoneyTransfer" {
EcFixedPointShort VALUE_COMMIT_VALUE,
EcFixedPoint VALUE_COMMIT_RANDOM,
EcFixedPointBase NULLIFIER_K,
}
witness "DaoAuthMoneyTransfer" {
@@ -20,8 +21,7 @@ witness "DaoAuthMoneyTransfer" {
Base dao_approval_ratio_quot,
Base dao_approval_ratio_base,
Base gov_token_id,
Base dao_public_x,
Base dao_public_y,
EcNiPoint dao_public_key,
Base dao_bulla_blind,
# Dao input(s) user data blind
@@ -29,14 +29,24 @@ witness "DaoAuthMoneyTransfer" {
# Dao output coin attrs
Base dao_value,
Base dao_token,
Base dao_token_id,
Base dao_serial,
# Should be set to DAO_CONTRACT_ID
Base dao_contract_id,
# Epehemeral secret used for diffie-hellman shared secret derivation
Base ephem_secret,
}
circuit "DaoAuthMoneyTransfer" {
# cast to EcPoint
# (otherwise zkas refuses to compile)
ONE = witness_base(1);
dao_pubkey = ec_mul_var_base(ONE, dao_public_key);
dao_public_x = ec_get_x(dao_pubkey);
dao_public_y = ec_get_y(dao_pubkey);
dao_bulla = poseidon_hash(
dao_proposer_limit,
dao_quorum,
@@ -74,7 +84,7 @@ circuit "DaoAuthMoneyTransfer" {
# which ensures it will be correct.
dao_value,
# Likewise the token_id must match the other output coins.
dao_token,
dao_token_id,
dao_serial,
dao_contract_id,
dao_bulla,
@@ -85,5 +95,36 @@ circuit "DaoAuthMoneyTransfer" {
# Reveal content commit. This should contain the set of coins.
# We check these are set in the runtime.
constrain_instance(proposal_auth_calls_commit);
# Now do verifiable encryption for DAO change output
# Ephemeral public key
ephem_public = ec_mul_base(ephem_secret, NULLIFIER_K);
constrain_instance(ec_get_x(ephem_public));
constrain_instance(ec_get_y(ephem_public));
# The shared_point C = eP = dE
shared_point = ec_mul_var_base(ephem_secret, dao_public_key);
shared_secret = poseidon_hash(
ec_get_x(shared_point),
ec_get_y(shared_point),
);
const_1 = witness_base(1);
const_2 = witness_base(2);
# Value
enc_value = base_add(dao_value, shared_secret);
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);
constrain_instance(enc_token_id);
# Serial
shared_secret_2 = poseidon_hash(shared_secret, const_2);
enc_serial = base_add(dao_serial, shared_secret_2);
constrain_instance(enc_serial);
}

View File

@@ -122,15 +122,37 @@ impl DaoAuthMoneyTransferCall {
// Build the main proof
let params = DaoAuthMoneyTransferParams { enc_attrs };
let ephem_secret = pallas::Base::random(&mut OsRng);
let change_ephem_pubkey = PublicKey::from_secret(ephem_secret.into());
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 dao_proposer_limit = pallas::Base::from(self.dao.proposer_limit);
let dao_quorum = pallas::Base::from(self.dao.quorum);
let dao_approval_ratio_quot = pallas::Base::from(self.dao.approval_ratio_quot);
let dao_approval_ratio_base = pallas::Base::from(self.dao.approval_ratio_base);
let (dao_pub_x, dao_pub_y) = self.dao.public_key.xy();
let input_user_data_enc =
poseidon_hash([self.dao.to_bulla().inner(), self.input_user_data_blind]);
@@ -147,17 +169,18 @@ impl DaoAuthMoneyTransferCall {
Witness::Base(Value::known(dao_approval_ratio_quot)),
Witness::Base(Value::known(dao_approval_ratio_base)),
Witness::Base(Value::known(self.dao.gov_token_id.inner())),
Witness::Base(Value::known(dao_pub_x)),
Witness::Base(Value::known(dao_pub_y)),
Witness::EcNiPoint(Value::known(dao_public_key)),
Witness::Base(Value::known(self.dao.bulla_blind)),
// Dao input user data blind
Witness::Base(Value::known(self.input_user_data_blind)),
// Dao output coin attrs
Witness::Base(Value::known(pallas::Base::from(self.dao_coin_attrs.value))),
Witness::Base(Value::known(dao_change_value)),
Witness::Base(Value::known(self.dao_coin_attrs.token_id.inner())),
Witness::Base(Value::known(self.dao_coin_attrs.serial)),
// DAO_CONTRACT_ID
Witness::Base(Value::known(DAO_CONTRACT_ID.inner())),
// Encrypted change DAO output
Witness::Base(Value::known(ephem_secret)),
];
let public_inputs = vec![
@@ -166,6 +189,11 @@ impl DaoAuthMoneyTransferCall {
self.dao_coin_attrs.to_coin().inner(),
DAO_CONTRACT_ID.inner(),
self.proposal.auth_calls.commit(),
ephem_x,
ephem_y,
change_enc_value,
change_enc_token_id,
change_enc_serial,
];
let circuit = ZkCircuit::new(prover_witnesses, auth_xfer_zkbin);

View File

@@ -84,6 +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();
zk_public_inputs.push((
DAO_CONTRACT_ZKAS_DAO_AUTH_MONEY_TRANSFER_NS.to_string(),
vec![
@@ -92,6 +93,11 @@ pub(crate) fn dao_authxfer_get_metadata(
last_coin.inner(),
DAO_CONTRACT_ID.inner(),
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,
],
));

View File

@@ -365,18 +365,23 @@ pub struct DaoExecUpdate {
/// 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,
}
// 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,
pub ephem_pubkey: PublicKey,
}
// 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 = "9d99da4cc2fa2882e5529bb6b24a965a815a2a22dc699d5e58ad17182e9f92a7";
const PKS_HASH: &str = "83f2577d4036bd92c2502d11b7af5c37bbe350bc17f2a2cd96bd4b7e16e4cebf";
const VKS_HASH: &str = "81036e85adea1b407698b0a3f58020f69ed6ac6c7843243b8b7b026d165f237f";
const PKS_HASH: &str = "40c0c448274dfe66ec4249a38e69b1c2f7fd971cc3d35fbb2129f4ee8ee8aea5";
fn pks_path(typ: &str) -> Result<PathBuf> {
let output = Command::new("git").arg("rev-parse").arg("--show-toplevel").output()?.stdout;