contracts: cosmetic cleaning up of proofs by prefixing attributes in bulla (kinda like is popular for postgres attributes in a table)

This commit is contained in:
zero
2024-02-06 17:46:56 +01:00
parent 4e92dafafe
commit 0b9c3eff5f
15 changed files with 165 additions and 154 deletions

View File

@@ -9,11 +9,11 @@ constant "DaoAuthMoneyTransferEncCoin" {
witness "DaoAuthMoneyTransferEncCoin" {
# Coin attributes
EcNiPoint public_key,
Base value,
Base token_id,
Base spend_hook,
Base user_data,
EcNiPoint coin_public_key,
Base coin_value,
Base coin_token_id,
Base coin_spend_hook,
Base coin_user_data,
Base coin_blind,
# Epehemeral secret used for diffie-hellman shared secret derivation
@@ -24,15 +24,15 @@ circuit "DaoAuthMoneyTransferEncCoin" {
# cast to EcPoint
# (otherwise zkas refuses to compile)
ONE = witness_base(1);
pubkey = ec_mul_var_base(ONE, public_key);
pubkey = ec_mul_var_base(ONE, coin_public_key);
coin = poseidon_hash(
ec_get_x(pubkey),
ec_get_y(pubkey),
value,
token_id,
spend_hook,
user_data,
coin_value,
coin_token_id,
coin_spend_hook,
coin_user_data,
coin_blind,
);
constrain_instance(coin);
@@ -44,7 +44,7 @@ circuit "DaoAuthMoneyTransferEncCoin" {
constrain_instance(ec_get_y(ephem_public));
# The shared_point C = eP = dE
shared_point = ec_mul_var_base(ephem_secret, public_key);
shared_point = ec_mul_var_base(ephem_secret, coin_public_key);
shared_secret = poseidon_hash(
ec_get_x(shared_point),
ec_get_y(shared_point),
@@ -58,26 +58,26 @@ circuit "DaoAuthMoneyTransferEncCoin" {
const_4 = witness_base(4);
const_5 = witness_base(5);
# Each blinding value must be used only once otherwise they
# Each blinding coin_value must be used only once otherwise they
# could be calculated.
# We can skip the public_key since it's inferred by the receiver
# We can skip the coin_public_key since it's inferred by the receiver
shared_secret_1 = poseidon_hash(shared_secret, const_1);
enc_value = base_add(value, shared_secret_1);
constrain_instance(enc_value);
enc_coin_value = base_add(coin_value, shared_secret_1);
constrain_instance(enc_coin_value);
shared_secret_2 = poseidon_hash(shared_secret, const_2);
enc_token_id = base_add(token_id, shared_secret_2);
constrain_instance(enc_token_id);
enc_coin_token_id = base_add(coin_token_id, shared_secret_2);
constrain_instance(enc_coin_token_id);
shared_secret_3 = poseidon_hash(shared_secret, const_3);
enc_spend_hook = base_add(spend_hook, shared_secret_3);
constrain_instance(enc_spend_hook);
enc_coin_spend_hook = base_add(coin_spend_hook, shared_secret_3);
constrain_instance(enc_coin_spend_hook);
shared_secret_4 = poseidon_hash(shared_secret, const_4);
enc_user_data = base_add(user_data, shared_secret_4);
constrain_instance(enc_user_data);
enc_coin_user_data = base_add(coin_user_data, shared_secret_4);
constrain_instance(enc_coin_user_data);
shared_secret_5 = poseidon_hash(shared_secret, const_5);
enc_coin_blind = base_add(coin_blind, shared_secret_5);

View File

@@ -20,7 +20,7 @@ witness "DaoAuthMoneyTransfer" {
Base dao_quorum,
Base dao_approval_ratio_quot,
Base dao_approval_ratio_base,
Base gov_token_id,
Base dao_gov_token_id,
EcNiPoint dao_public_key,
Base dao_bulla_blind,
@@ -52,7 +52,7 @@ circuit "DaoAuthMoneyTransfer" {
dao_quorum,
dao_approval_ratio_quot,
dao_approval_ratio_base,
gov_token_id,
dao_gov_token_id,
dao_public_x,
dao_public_y,
dao_bulla_blind,

View File

@@ -20,7 +20,7 @@ witness "DaoExec" {
Base dao_quorum,
Base dao_approval_ratio_quot,
Base dao_approval_ratio_base,
Base gov_token_id,
Base dao_gov_token_id,
Base dao_public_x,
Base dao_public_y,
Base dao_bulla_blind,
@@ -41,7 +41,7 @@ circuit "DaoExec" {
dao_quorum,
dao_approval_ratio_quot,
dao_approval_ratio_base,
gov_token_id,
dao_gov_token_id,
dao_public_x,
dao_public_y,
dao_bulla_blind,

View File

@@ -11,7 +11,7 @@ witness "DaoMint" {
Base dao_quorum,
Base dao_approval_ratio_quot,
Base dao_approval_ratio_base,
Base gov_token_id,
Base dao_gov_token_id,
Base dao_secret,
Base dao_bulla_blind,
}
@@ -30,7 +30,7 @@ circuit "DaoMint" {
dao_quorum,
dao_approval_ratio_quot,
dao_approval_ratio_base,
gov_token_id,
dao_gov_token_id,
dao_public_x,
dao_public_y,
dao_bulla_blind,

View File

@@ -8,50 +8,53 @@ constant "DaoProposeInput" {
}
witness "DaoProposeInput" {
Base secret,
Base spend_hook,
Base user_data,
Base coin_secret,
Base coin_value,
Base coin_token,
Base coin_spend_hook,
Base coin_user_data,
Base coin_blind,
Base value,
Base token,
Scalar value_blind,
Base token_blind,
Base coin_token_blind,
Uint32 leaf_pos,
MerklePath path,
Base signature_secret,
}
circuit "DaoProposeInput" {
# Coin hash
pub = ec_mul_base(secret, NULLIFIER_K);
pub = ec_mul_base(coin_secret, NULLIFIER_K);
pub_x = ec_get_x(pub);
pub_y = ec_get_y(pub);
coin = poseidon_hash(
pub_x,
pub_y,
value,
token,
spend_hook,
user_data,
coin_value,
coin_token,
coin_spend_hook,
coin_user_data,
coin_blind,
);
# We need this to detect whether the above coin was already spent.
# To avoid leaking timing & other info, we can just make a
# money::transfer() call within the same tx.
nullifier = poseidon_hash(secret, coin);
nullifier = poseidon_hash(coin_secret, coin);
constrain_instance(nullifier);
# Pedersen commitment for coin's value
vcv = ec_mul_short(value, VALUE_COMMIT_VALUE);
# Pedersen commitment for coin's coin_value
vcv = ec_mul_short(coin_value, VALUE_COMMIT_VALUE);
vcr = ec_mul(value_blind, VALUE_COMMIT_RANDOM);
value_commit = ec_add(vcv, vcr);
constrain_instance(ec_get_x(value_commit));
constrain_instance(ec_get_y(value_commit));
coin_value_commit = ec_add(vcv, vcr);
constrain_instance(ec_get_x(coin_value_commit));
constrain_instance(ec_get_y(coin_value_commit));
# Commitment for coin's token ID
token_commit = poseidon_hash(token, token_blind);
constrain_instance(token_commit);
# Commitment for coin's coin_token ID
coin_token_commit = poseidon_hash(coin_token, coin_token_blind);
constrain_instance(coin_token_commit);
# Merkle root
root = merkle_root(leaf_pos, path, coin);

View File

@@ -26,7 +26,7 @@ witness "DaoProposeMain" {
Base dao_quorum,
Base dao_approval_ratio_quot,
Base dao_approval_ratio_base,
Base gov_token_id,
Base dao_gov_token_id,
Base dao_public_x,
Base dao_public_y,
Base dao_bulla_blind,
@@ -36,7 +36,7 @@ witness "DaoProposeMain" {
}
circuit "DaoProposeMain" {
token_commit = poseidon_hash(gov_token_id, gov_token_blind);
token_commit = poseidon_hash(dao_gov_token_id, gov_token_blind);
constrain_instance(token_commit);
dao_bulla = poseidon_hash(
@@ -44,7 +44,7 @@ circuit "DaoProposeMain" {
dao_quorum,
dao_approval_ratio_quot,
dao_approval_ratio_base,
gov_token_id,
dao_gov_token_id,
dao_public_x,
dao_public_y,
dao_bulla_blind,

View File

@@ -8,30 +8,33 @@ constant "DaoVoteInput" {
}
witness "DaoVoteInput" {
Base secret,
Base spend_hook,
Base user_data,
Base coin_secret,
Base coin_value,
Base coin_gov_token_id,
Base coin_spend_hook,
Base coin_user_data,
Base coin_blind,
Base value,
Base gov_token_id,
Scalar value_blind,
Base gov_token_blind,
Uint32 leaf_pos,
MerklePath path,
Base signature_secret,
}
circuit "DaoVoteInput" {
pub = ec_mul_base(secret, NULLIFIER_K);
pub = ec_mul_base(coin_secret, NULLIFIER_K);
pub_x = ec_get_x(pub);
pub_y = ec_get_y(pub);
coin = poseidon_hash(
pub_x,
pub_y,
value,
gov_token_id,
spend_hook,
user_data,
coin_value,
coin_gov_token_id,
coin_spend_hook,
coin_user_data,
coin_blind,
);
@@ -41,16 +44,16 @@ circuit "DaoVoteInput" {
# limitation where votes across proposals are linked where this
# coin is active. The best fix would be the set non-membership,
# but that possibly has scaling issues.
nullifier = poseidon_hash(secret, coin);
nullifier = poseidon_hash(coin_secret, coin);
constrain_instance(nullifier);
vcv = ec_mul_short(value, VALUE_COMMIT_VALUE);
vcv = ec_mul_short(coin_value, VALUE_COMMIT_VALUE);
vcr = ec_mul(value_blind, VALUE_COMMIT_RANDOM);
value_commit = ec_add(vcv, vcr);
constrain_instance(ec_get_x(value_commit));
constrain_instance(ec_get_y(value_commit));
coin_value_commit = ec_add(vcv, vcr);
constrain_instance(ec_get_x(coin_value_commit));
constrain_instance(ec_get_y(coin_value_commit));
token_commit = poseidon_hash(gov_token_id, gov_token_blind);
token_commit = poseidon_hash(coin_gov_token_id, gov_token_blind);
constrain_instance(token_commit);
# Merkle root

View File

@@ -21,7 +21,7 @@ witness "DaoVoteMain" {
Base dao_quorum,
Base dao_approval_ratio_quot,
Base dao_approval_ratio_base,
Base gov_token_id,
Base dao_gov_token_id,
EcNiPoint dao_public_key,
Base dao_bulla_blind,
@@ -43,7 +43,7 @@ witness "DaoVoteMain" {
}
circuit "DaoVoteMain" {
token_commit = poseidon_hash(gov_token_id, gov_token_blind);
token_commit = poseidon_hash(dao_gov_token_id, gov_token_blind);
constrain_instance(token_commit);
# cast to EcPoint
@@ -58,7 +58,7 @@ circuit "DaoVoteMain" {
dao_quorum,
dao_approval_ratio_quot,
dao_approval_ratio_base,
gov_token_id,
dao_gov_token_id,
dao_public_x,
dao_public_y,
dao_bulla_blind,

View File

@@ -82,11 +82,11 @@ impl DaoProposeCall {
let prover_witnesses = vec![
Witness::Base(Value::known(input.secret.inner())),
Witness::Base(Value::known(pallas::Base::from(note.value))),
Witness::Base(Value::known(note.token_id.inner())),
Witness::Base(Value::known(pallas::Base::ZERO)),
Witness::Base(Value::known(pallas::Base::ZERO)),
Witness::Base(Value::known(note.coin_blind)),
Witness::Base(Value::known(pallas::Base::from(note.value))),
Witness::Base(Value::known(note.token_id.inner())),
Witness::Scalar(Value::known(funds_blind)),
Witness::Base(Value::known(gov_token_blind)),
Witness::Uint32(Value::known(leaf_pos.try_into().unwrap())),

View File

@@ -107,11 +107,11 @@ impl DaoVoteCall {
let prover_witnesses = vec![
Witness::Base(Value::known(input.secret.inner())),
Witness::Base(Value::known(pallas::Base::from(note.value))),
Witness::Base(Value::known(note.token_id.inner())),
Witness::Base(Value::known(pallas::Base::ZERO)),
Witness::Base(Value::known(pallas::Base::ZERO)),
Witness::Base(Value::known(note.coin_blind)),
Witness::Base(Value::known(pallas::Base::from(note.value))),
Witness::Base(Value::known(note.token_id.inner())),
Witness::Scalar(Value::known(value_blind)),
Witness::Base(Value::known(gov_token_blind)),
Witness::Uint32(Value::known(leaf_pos.try_into().unwrap())),

View File

@@ -9,30 +9,34 @@ constant "Burn_V1" {
EcFixedPointBase NULLIFIER_K,
}
# The witness values we define for our circuit
# The witness coin_values we define for our circuit
witness "Burn_V1" {
# The value of this coin
Base value,
# The token ID
Base token,
# Random blinding factor for value commitment
Scalar value_blind,
# Random blinding factor for the token ID
Base token_blind,
# Secret key used to derive nullifier and coin's public key
Base coin_secret,
# The coin_value of this coin
Base coin_value,
# The coin_token_id ID
Base coin_token_id,
# Allows composing this ZK proof to invoke other contracts
Base spend_hook,
Base coin_spend_hook,
# Data passed from this coin to the invoked contract
Base user_data,
Base coin_user_data,
# Unique serial number corresponding to this coin
Base coin_blind,
# Blinding factor for the encrypted user_data
# Random blinding factor for coin_value commitment
Scalar value_blind,
# Random blinding factor for the coin_token_id ID
Base token_id_blind,
# Blinding factor for the encrypted coin_user_data
Base user_data_blind,
# Secret key used to derive nullifier and coin's public key
Base secret,
# Leaf position of the coin in the Merkle tree of coins
Uint32 leaf_pos,
# Merkle path to the coin
MerklePath path,
# Secret key used to derive public key for the tx signature
Base signature_secret,
}
@@ -40,53 +44,53 @@ witness "Burn_V1" {
# The definition of our circuit
circuit "Burn_V1" {
# Derive the public key used in the coin from its secret counterpart
pub = ec_mul_base(secret, NULLIFIER_K);
pub = ec_mul_base(coin_secret, NULLIFIER_K);
# Coin hash
coin = poseidon_hash(
ec_get_x(pub),
ec_get_y(pub),
value,
token,
spend_hook,
user_data,
coin_value,
coin_token_id,
coin_spend_hook,
coin_user_data,
coin_blind,
);
# Poseidon hash of the nullifier
nullifier = poseidon_hash(secret, coin);
nullifier = poseidon_hash(coin_secret, coin);
constrain_instance(nullifier);
# Pedersen commitment for coin's value
vcv = ec_mul_short(value, VALUE_COMMIT_VALUE);
# Pedersen commitment for coin's coin_value
vcv = ec_mul_short(coin_value, VALUE_COMMIT_VALUE);
vcr = ec_mul(value_blind, VALUE_COMMIT_RANDOM);
value_commit = ec_add(vcv, vcr);
# Since value_commit is a curve point, we fetch its coordinates
coin_value_commit = ec_add(vcv, vcr);
# Since coin_value_commit is a curve point, we fetch its coordinates
# and constrain them:
constrain_instance(ec_get_x(value_commit));
constrain_instance(ec_get_y(value_commit));
constrain_instance(ec_get_x(coin_value_commit));
constrain_instance(ec_get_y(coin_value_commit));
# Commitment for coin's token ID. We do a poseidon hash since it's
# Commitment for coin's coin_token_id ID. We do a poseidon hash since it's
# cheaper than EC operations and doesn't need the homomorphic prop.
token_commit = poseidon_hash(token, token_blind);
constrain_instance(token_commit);
coin_token_id_commit = poseidon_hash(coin_token_id, token_id_blind);
constrain_instance(coin_token_id_commit);
# With this, we can actually produce a fake coin of value 0
# With this, we can actually produce a fake coin of coin_value 0
# above and use it as a dummy input. The inclusion merkle tree
# has a 0x00 leaf at position 0, so zero_cond will output value
# iff value is 0 - which is equivalent to 0x00 so that's the
# has a 0x00 leaf at position 0, so zero_cond will output coin_value
# iff coin_value is 0 - which is equivalent to 0x00 so that's the
# trick we use to make the inclusion proof.
coin_incl = zero_cond(value, coin);
coin_incl = zero_cond(coin_value, coin);
# Merkle root
root = merkle_root(leaf_pos, path, coin_incl);
constrain_instance(root);
# Export user_data
user_data_enc = poseidon_hash(user_data, user_data_blind);
constrain_instance(user_data_enc);
# Export coin_user_data
coin_user_data_enc = poseidon_hash(coin_user_data, user_data_blind);
constrain_instance(coin_user_data_enc);
# Reveal spend_hook
constrain_instance(spend_hook);
# Reveal coin_spend_hook
constrain_instance(coin_spend_hook);
# Finally, we derive a public key for the signature and
# constrain its coordinates:

View File

@@ -9,55 +9,56 @@ constant "Mint_V1" {
EcFixedPointBase NULLIFIER_K,
}
# The witness values we define for our circuit
# The witness coin_values we define for our circuit
witness "Mint_V1" {
# X coordinate for public key
Base pub_x,
Base coin_public_x,
# Y coordinate for public key
Base pub_y,
# The value of this coin
Base value,
# The token ID
Base token,
Base coin_public_y,
# The coin_value of this coin
Base coin_value,
# The coin_token_id ID
Base coin_token_id,
# Allows composing this ZK proof to invoke other contracts
Base spend_hook,
Base coin_spend_hook,
# Data passed from this coin to the invoked contract
Base user_data,
Base coin_user_data,
# Unique serial number corresponding to this coin
Base coin_blind,
# Random blinding factor for the value commitment
# Random blinding factor for the coin_value commitment
Scalar value_blind,
# Random blinding factor for the token ID
Base token_blind,
# Random blinding factor for the coin_token_id ID
Base token_id_blind,
}
# The definition of our circuit
circuit "Mint_V1" {
# Poseidon hash of the coin
C = poseidon_hash(
pub_x,
pub_y,
value,
token,
spend_hook,
user_data,
coin_public_x,
coin_public_y,
coin_value,
coin_token_id,
coin_spend_hook,
coin_user_data,
coin_blind,
);
constrain_instance(C);
# Pedersen commitment for coin's value
vcv = ec_mul_short(value, VALUE_COMMIT_VALUE);
# Pedersen commitment for coin's coin_value
vcv = ec_mul_short(coin_value, VALUE_COMMIT_VALUE);
vcr = ec_mul(value_blind, VALUE_COMMIT_RANDOM);
value_commit = ec_add(vcv, vcr);
# Since the value commit is a curve point, we fetch its coordinates
coin_value_commit = ec_add(vcv, vcr);
# Since the coin_value commit is a curve point, we fetch its coordinates
# and constrain them:
constrain_instance(ec_get_x(value_commit));
constrain_instance(ec_get_y(value_commit));
constrain_instance(ec_get_x(coin_value_commit));
constrain_instance(ec_get_y(coin_value_commit));
# Commitment for coin's token ID. We do a poseidon hash since it's
# Commitment for coin's coin_token_id ID. We do a poseidon hash since it's
# cheaper than EC operations and doesn't need the homomorphic prop.
token_commit = poseidon_hash(token, token_blind);
constrain_instance(token_commit);
coin_token_id_commit = poseidon_hash(coin_token_id, token_id_blind);
constrain_instance(coin_token_id_commit);
# At this point we've enforced all of our public inputs.
}

View File

@@ -10,16 +10,16 @@ constant "TokenMint_V1" {
witness "TokenMint_V1" {
# CoinAttributes {
Base public_x,
Base public_y,
Base value,
Base spend_hook,
Base coin_public_x,
Base coin_public_y,
Base coin_value,
Base coin_spend_hook,
Base coin_user_data,
Base coin_blind,
# }
# TokenAttributes {
Base auth_parent,
Base token_auth_parent,
Base token_user_data,
Base token_blind,
# }
@@ -27,16 +27,16 @@ witness "TokenMint_V1" {
circuit "TokenMint_V1" {
# Derive the token ID
token_id = poseidon_hash(auth_parent, token_user_data, token_blind);
constrain_instance(auth_parent);
token_id = poseidon_hash(token_auth_parent, token_user_data, token_blind);
constrain_instance(token_auth_parent);
# Then show the coin contains the token ID
coin = poseidon_hash(
public_x,
public_y,
value,
coin_public_x,
coin_public_y,
coin_value,
token_id,
spend_hook,
coin_spend_hook,
coin_user_data,
coin_blind,
);

View File

@@ -133,15 +133,15 @@ pub fn create_transfer_burn_proof(
};
let prover_witnesses = vec![
Witness::Base(Value::known(input.secret.inner())),
Witness::Base(Value::known(pallas::Base::from(input.note.value))),
Witness::Base(Value::known(input.note.token_id.inner())),
Witness::Scalar(Value::known(value_blind)),
Witness::Base(Value::known(token_blind)),
Witness::Base(Value::known(input.note.spend_hook.inner())),
Witness::Base(Value::known(input.note.user_data)),
Witness::Base(Value::known(input.note.coin_blind)),
Witness::Scalar(Value::known(value_blind)),
Witness::Base(Value::known(token_blind)),
Witness::Base(Value::known(input.user_data_blind)),
Witness::Base(Value::known(input.secret.inner())),
Witness::Uint32(Value::known(u64::from(input.leaf_position).try_into().unwrap())),
Witness::MerklePath(Value::known(input.merkle_path.clone().try_into().unwrap())),
Witness::Base(Value::known(signature_secret.inner())),

View File

@@ -47,8 +47,8 @@ use darkfi_serial::{deserialize, serialize};
use log::debug;
/// Update this if any circuits are changed
const VKS_HASH: &str = "2f0fbe2efd2b513bd22bfbfde4ad3db0c5730706092aa3cd5d63cefee62a31a6";
const PKS_HASH: &str = "cb81c8c7da7000bab623ab1d9fe548aba9e335199016c60339df198358f556d5";
const VKS_HASH: &str = "665562975ac7634cc4a028c74f641d28c9e3aaeb27d27ec9474995f02d23cd6a";
const PKS_HASH: &str = "47e0e4cea6127377da30f97b17c748e7b2204261f168401103fa346b9426ea60";
fn pks_path(typ: &str) -> Result<PathBuf> {
let output = Command::new("git").arg("rev-parse").arg("--show-toplevel").output()?.stdout;