mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-08 22:28:12 -05:00
crypto: Rework pedersen commitments to allow also full-width base inside zk.
This commit is contained in:
2
Makefile
2
Makefile
@@ -10,7 +10,7 @@ CARGO = cargo
|
||||
#RUSTFLAGS = -C target-cpu=native
|
||||
|
||||
# Binaries to be built
|
||||
BINS = zkas drk darkfid tau taud ircd dnetview
|
||||
BINS = zkas drk darkfid tau taud ircd dnetview darkotc
|
||||
|
||||
# Common dependencies which should force the binaries to be rebuilt
|
||||
BINDEPS = \
|
||||
|
||||
@@ -23,7 +23,7 @@ use darkfi::{
|
||||
proof::ProvingKey,
|
||||
token_id,
|
||||
types::{DrkCoinBlind, DrkSerial, DrkTokenId, DrkValueBlind},
|
||||
util::{mod_r_p, pedersen_commitment_scalar, pedersen_commitment_u64},
|
||||
util::{pedersen_commitment_base, pedersen_commitment_u64},
|
||||
BurnRevealedValues, MintRevealedValues, OwnCoin, Proof,
|
||||
},
|
||||
rpc::{client::RpcClient, jsonrpc::JsonRequest},
|
||||
@@ -382,8 +382,7 @@ fn inspect(data: &str) -> Result<()> {
|
||||
burn_value_valid = true;
|
||||
}
|
||||
|
||||
if pedersen_commitment_scalar(mod_r_p(sd.burn_token), sd.burn_token_blind) ==
|
||||
sd.burn_revealed.token_commit
|
||||
if pedersen_commitment_base(sd.burn_token, sd.burn_token_blind) == sd.burn_revealed.token_commit
|
||||
{
|
||||
burn_token_valid = true;
|
||||
}
|
||||
@@ -393,8 +392,7 @@ fn inspect(data: &str) -> Result<()> {
|
||||
mint_value_valid = true;
|
||||
}
|
||||
|
||||
if pedersen_commitment_scalar(mod_r_p(sd.mint_token), sd.mint_token_blind) ==
|
||||
sd.mint_revealed.token_commit
|
||||
if pedersen_commitment_base(sd.mint_token, sd.mint_token_blind) == sd.mint_revealed.token_commit
|
||||
{
|
||||
mint_token_valid = true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Example transaction flow
|
||||
use incrementalmerkletree::{bridgetree::BridgeTree, Tree};
|
||||
use pasta_curves::{group::ff::Field, pallas};
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
use darkfi::{
|
||||
@@ -10,7 +11,6 @@ use darkfi::{
|
||||
note::{EncryptedNote, Note},
|
||||
nullifier::Nullifier,
|
||||
proof::{ProvingKey, VerifyingKey},
|
||||
token_id::generate_id,
|
||||
OwnCoin, OwnCoins,
|
||||
},
|
||||
node::state::{state_transition, ProgramState, StateUpdate},
|
||||
@@ -18,7 +18,6 @@ use darkfi::{
|
||||
TransactionBuilder, TransactionBuilderClearInputInfo, TransactionBuilderInputInfo,
|
||||
TransactionBuilderOutputInfo,
|
||||
},
|
||||
util::NetworkName,
|
||||
zk::circuit::{BurnContract, MintContract},
|
||||
Result,
|
||||
};
|
||||
@@ -127,7 +126,7 @@ fn main() -> Result<()> {
|
||||
|
||||
let keypair = Keypair::random(&mut OsRng);
|
||||
|
||||
let mint_vk = VerifyingKey::build(8, &MintContract::default());
|
||||
let mint_vk = VerifyingKey::build(11, &MintContract::default());
|
||||
let burn_vk = VerifyingKey::build(11, &BurnContract::default());
|
||||
|
||||
let mut state = MemoryState {
|
||||
@@ -142,8 +141,7 @@ fn main() -> Result<()> {
|
||||
secrets: vec![keypair.secret],
|
||||
};
|
||||
|
||||
let token_id =
|
||||
generate_id(&NetworkName::Solana, "So11111111111111111111111111111111111111112")?;
|
||||
let token_id = pallas::Base::random(&mut OsRng);
|
||||
|
||||
let builder = TransactionBuilder {
|
||||
clear_inputs: vec![TransactionBuilderClearInputInfo {
|
||||
@@ -159,7 +157,7 @@ fn main() -> Result<()> {
|
||||
}],
|
||||
};
|
||||
|
||||
let mint_pk = ProvingKey::build(8, &MintContract::default());
|
||||
let mint_pk = ProvingKey::build(11, &MintContract::default());
|
||||
let burn_pk = ProvingKey::build(11, &BurnContract::default());
|
||||
let tx = builder.build(&mint_pk, &burn_pk)?;
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ circuit "Burn" {
|
||||
constrain_instance(value_commit_y);
|
||||
|
||||
# Pedersen commitment for coin's token ID
|
||||
tcv = ec_mul_short(token, VALUE_COMMIT_VALUE);
|
||||
tcv = ec_mul_base(token, NULLIFIER_K);
|
||||
tcr = ec_mul(token_blind, VALUE_COMMIT_RANDOM);
|
||||
token_commit = ec_add(tcv, tcr);
|
||||
# Since token_commit is also a curve point, we'll do the same
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
constant "Mint" {
|
||||
EcFixedPointShort VALUE_COMMIT_VALUE,
|
||||
EcFixedPoint VALUE_COMMIT_RANDOM,
|
||||
EcFixedPointBase NULLIFIER_K,
|
||||
}
|
||||
|
||||
contract "Mint" {
|
||||
@@ -31,7 +32,7 @@ circuit "Mint" {
|
||||
constrain_instance(value_commit_y);
|
||||
|
||||
# Pedersen commitment for coin's token ID
|
||||
tcv = ec_mul_short(token, VALUE_COMMIT_VALUE);
|
||||
tcv = ec_mul_base(token, NULLIFIER_K);
|
||||
tcr = ec_mul(token_blind, VALUE_COMMIT_RANDOM);
|
||||
token_commit = ec_add(tcv, tcr);
|
||||
# Since token_commit is also a curve point, we'll do the same
|
||||
|
||||
@@ -10,7 +10,7 @@ use rand::rngs::OsRng;
|
||||
use super::{
|
||||
nullifier::Nullifier,
|
||||
proof::{Proof, ProvingKey, VerifyingKey},
|
||||
util::{mod_r_p, pedersen_commitment_scalar, pedersen_commitment_u64},
|
||||
util::{pedersen_commitment_base, pedersen_commitment_u64},
|
||||
};
|
||||
use crate::{
|
||||
crypto::{
|
||||
@@ -76,7 +76,7 @@ impl BurnRevealedValues {
|
||||
};
|
||||
|
||||
let value_commit = pedersen_commitment_u64(value, value_blind);
|
||||
let token_commit = pedersen_commitment_scalar(mod_r_p(token_id), token_blind);
|
||||
let token_commit = pedersen_commitment_base(token_id, token_blind);
|
||||
|
||||
BurnRevealedValues {
|
||||
value_commit,
|
||||
|
||||
@@ -272,7 +272,7 @@ impl<'de> serde::Deserialize<'de> for PublicKey {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
crypto::util::pedersen_commitment_scalar,
|
||||
crypto::util::pedersen_commitment_base,
|
||||
util::serial::{deserialize, serialize},
|
||||
};
|
||||
|
||||
@@ -300,15 +300,15 @@ mod tests {
|
||||
);
|
||||
assert_eq!(deserialize(&serialized).ok(), Some(fourtwenty));
|
||||
|
||||
let a = pallas::Scalar::from(420);
|
||||
let a = pallas::Base::from(420);
|
||||
let b = pallas::Scalar::from(69);
|
||||
let pc: pallas::Point = pedersen_commitment_scalar(a, b);
|
||||
let pc: pallas::Point = pedersen_commitment_base(a, b);
|
||||
let serialized = serialize(&pc);
|
||||
assert_eq!(
|
||||
serialized,
|
||||
vec![
|
||||
55, 48, 126, 42, 114, 27, 18, 55, 155, 141, 83, 75, 44, 50, 244, 223, 254, 216, 22,
|
||||
167, 208, 59, 212, 201, 150, 149, 96, 207, 216, 74, 60, 131
|
||||
57, 232, 32, 239, 229, 119, 41, 70, 218, 174, 237, 25, 122, 81, 81, 252, 54, 192,
|
||||
225, 207, 145, 124, 177, 46, 28, 37, 55, 70, 6, 33, 51, 42,
|
||||
]
|
||||
);
|
||||
assert_eq!(deserialize(&serialized).ok(), Some(pc));
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::{
|
||||
keypair::PublicKey,
|
||||
proof::{Proof, ProvingKey, VerifyingKey},
|
||||
types::{DrkCoinBlind, DrkSerial, DrkTokenId, DrkValue, DrkValueBlind, DrkValueCommit},
|
||||
util::{mod_r_p, pedersen_commitment_scalar, pedersen_commitment_u64},
|
||||
util::{pedersen_commitment_base, pedersen_commitment_u64},
|
||||
},
|
||||
util::serial::{SerialDecodable, SerialEncodable},
|
||||
zk::circuit::mint_contract::MintContract,
|
||||
@@ -37,7 +37,7 @@ impl MintRevealedValues {
|
||||
public_key: PublicKey,
|
||||
) -> Self {
|
||||
let value_commit = pedersen_commitment_u64(value, value_blind);
|
||||
let token_commit = pedersen_commitment_scalar(mod_r_p(token_id), token_blind);
|
||||
let token_commit = pedersen_commitment_base(token_id, token_blind);
|
||||
|
||||
let coords = public_key.0.to_affine().coordinates().unwrap();
|
||||
let messages =
|
||||
|
||||
@@ -118,7 +118,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_proof_serialization() -> Result<()> {
|
||||
let value = 110_u64;
|
||||
let token_id = DrkTokenId::from(42);
|
||||
let token_id = DrkTokenId::random(&mut OsRng);
|
||||
let value_blind = DrkValueBlind::random(&mut OsRng);
|
||||
let token_blind = DrkValueBlind::random(&mut OsRng);
|
||||
let serial = DrkSerial::random(&mut OsRng);
|
||||
|
||||
@@ -34,8 +34,7 @@ pub trait SchnorrPublic {
|
||||
impl SchnorrSecret for SecretKey {
|
||||
fn sign(&self, message: &[u8]) -> Signature {
|
||||
let mask = pallas::Scalar::random(&mut OsRng);
|
||||
let nfk = NullifierK;
|
||||
let commit = nfk.generator() * mask;
|
||||
let commit = NullifierK.generator() * mask;
|
||||
|
||||
let challenge = hash_to_scalar(DRK_SCHNORR_DOMAIN, &commit.to_bytes(), message);
|
||||
let response = mask + challenge * mod_r_p(self.0);
|
||||
@@ -47,8 +46,7 @@ impl SchnorrSecret for SecretKey {
|
||||
impl SchnorrPublic for PublicKey {
|
||||
fn verify(&self, message: &[u8], signature: &Signature) -> bool {
|
||||
let challenge = hash_to_scalar(DRK_SCHNORR_DOMAIN, &signature.commit.to_bytes(), message);
|
||||
let nfk = NullifierK;
|
||||
nfk.generator() * signature.response - self.0 * challenge == signature.commit
|
||||
NullifierK.generator() * signature.response - self.0 * challenge == signature.commit
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
use blake2b_simd::Params;
|
||||
use halo2_gadgets::ecc::chip::FixedPoint;
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveExt, FieldExt},
|
||||
group::ff::PrimeField,
|
||||
pallas,
|
||||
};
|
||||
|
||||
use super::constants::fixed_bases::{
|
||||
VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_R_BYTES, VALUE_COMMITMENT_V_BYTES,
|
||||
use super::{
|
||||
constants::{
|
||||
fixed_bases::{
|
||||
VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_R_BYTES, VALUE_COMMITMENT_V_BYTES,
|
||||
},
|
||||
util::gen_const_array,
|
||||
NullifierK,
|
||||
},
|
||||
types::*,
|
||||
};
|
||||
use crate::crypto::{constants::util::gen_const_array, types::*};
|
||||
|
||||
pub fn hash_to_scalar(persona: &[u8], a: &[u8], b: &[u8]) -> pallas::Scalar {
|
||||
let mut hasher = Params::new().hash_length(64).personal(persona).to_state();
|
||||
@@ -18,17 +25,24 @@ pub fn hash_to_scalar(persona: &[u8], a: &[u8], b: &[u8]) -> pallas::Scalar {
|
||||
pallas::Scalar::from_bytes_wide(ret.as_array())
|
||||
}
|
||||
|
||||
/// Pedersen commitment for a full-width base field element.
|
||||
#[allow(non_snake_case)]
|
||||
pub fn pedersen_commitment_scalar(value: pallas::Scalar, blind: DrkValueBlind) -> DrkValueCommit {
|
||||
pub fn pedersen_commitment_base(value: pallas::Base, blind: DrkValueBlind) -> DrkValueCommit {
|
||||
let hasher = DrkValueCommit::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION);
|
||||
let V = NullifierK.generator();
|
||||
let R = hasher(&VALUE_COMMITMENT_R_BYTES);
|
||||
|
||||
V * mod_r_p(value) + R * blind
|
||||
}
|
||||
|
||||
/// Pedersen commitment for a 64-bit value, in the base field.
|
||||
#[allow(non_snake_case)]
|
||||
pub fn pedersen_commitment_u64(value: u64, blind: DrkValueBlind) -> DrkValueCommit {
|
||||
let hasher = DrkValueCommit::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION);
|
||||
let V = hasher(&VALUE_COMMITMENT_V_BYTES);
|
||||
let R = hasher(&VALUE_COMMITMENT_R_BYTES);
|
||||
|
||||
V * value + R * blind
|
||||
}
|
||||
|
||||
pub fn pedersen_commitment_u64(value: u64, blind: DrkValueBlind) -> DrkValueCommit {
|
||||
pedersen_commitment_scalar(mod_r_p(DrkValue::from(value)), blind)
|
||||
V * mod_r_p(DrkValue::from(value)) + R * blind
|
||||
}
|
||||
|
||||
/// Converts from pallas::Base to pallas::Scalar (aka $x \pmod{r_\mathbb{P}}$).
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::{
|
||||
schnorr,
|
||||
schnorr::SchnorrPublic,
|
||||
types::{DrkTokenId, DrkValueBlind, DrkValueCommit},
|
||||
util::{mod_r_p, pedersen_commitment_scalar, pedersen_commitment_u64},
|
||||
util::{pedersen_commitment_base, pedersen_commitment_u64},
|
||||
BurnRevealedValues, MintRevealedValues, Proof,
|
||||
},
|
||||
impl_vec,
|
||||
@@ -163,8 +163,7 @@ impl Transaction {
|
||||
|
||||
failed = failed ||
|
||||
self.clear_inputs.iter().any(|input| {
|
||||
pedersen_commitment_scalar(mod_r_p(input.token_id), input.token_blind) !=
|
||||
token_commit_value
|
||||
pedersen_commitment_base(input.token_id, input.token_blind) != token_commit_value
|
||||
});
|
||||
!failed
|
||||
}
|
||||
|
||||
@@ -369,8 +369,7 @@ impl Circuit<pallas::Base> for BurnContract {
|
||||
|
||||
// v * G_1
|
||||
let (commitment, _) = {
|
||||
let value_commit_v = ValueCommitV;
|
||||
let value_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), value_commit_v);
|
||||
let value_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), ValueCommitV);
|
||||
let value = ScalarFixedShort::new(
|
||||
ecc_chip.clone(),
|
||||
layouter.namespace(|| "value"),
|
||||
@@ -386,8 +385,8 @@ impl Circuit<pallas::Base> for BurnContract {
|
||||
layouter.namespace(|| "value_blind"),
|
||||
self.value_blind,
|
||||
)?;
|
||||
let value_commit_r = OrchardFixedBasesFull::ValueCommitR;
|
||||
let value_commit_r = FixedPoint::from_inner(ecc_chip.clone(), value_commit_r);
|
||||
let value_commit_r =
|
||||
FixedPoint::from_inner(ecc_chip.clone(), OrchardFixedBasesFull::ValueCommitR);
|
||||
value_commit_r.mul(layouter.namespace(|| "[value_blind] ValueCommitR"), rcv)?
|
||||
};
|
||||
|
||||
@@ -412,15 +411,9 @@ impl Circuit<pallas::Base> for BurnContract {
|
||||
assign_free_advice(layouter.namespace(|| "load token"), config.advices[0], self.token)?;
|
||||
|
||||
// a * G_1
|
||||
let (commitment, _) = {
|
||||
let token_commit_v = ValueCommitV;
|
||||
let token_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), token_commit_v);
|
||||
let token = ScalarFixedShort::new(
|
||||
ecc_chip.clone(),
|
||||
layouter.namespace(|| "token"),
|
||||
(token, one),
|
||||
)?;
|
||||
token_commit_v.mul(layouter.namespace(|| "[token] ValueCommitV"), token)?
|
||||
let commitment = {
|
||||
let token_commit_v = FixedPointBaseField::from_inner(ecc_chip.clone(), NullifierK);
|
||||
token_commit_v.mul(layouter.namespace(|| "[token] NullifierK"), token)?
|
||||
};
|
||||
|
||||
// r_A * G_2
|
||||
@@ -430,8 +423,8 @@ impl Circuit<pallas::Base> for BurnContract {
|
||||
layouter.namespace(|| "token_blind"),
|
||||
self.token_blind,
|
||||
)?;
|
||||
let token_commit_r = OrchardFixedBasesFull::ValueCommitR;
|
||||
let token_commit_r = FixedPoint::from_inner(ecc_chip.clone(), token_commit_r);
|
||||
let token_commit_r =
|
||||
FixedPoint::from_inner(ecc_chip.clone(), OrchardFixedBasesFull::ValueCommitR);
|
||||
token_commit_r.mul(layouter.namespace(|| "[token_blind] ValueCommitR"), rca)?
|
||||
};
|
||||
|
||||
@@ -488,7 +481,7 @@ mod tests {
|
||||
crypto::{
|
||||
keypair::{PublicKey, SecretKey},
|
||||
proof::{ProvingKey, VerifyingKey},
|
||||
util::{mod_r_p, pedersen_commitment_scalar},
|
||||
util::{pedersen_commitment_base, pedersen_commitment_u64},
|
||||
Proof,
|
||||
},
|
||||
Result,
|
||||
@@ -506,8 +499,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn burn_circuit_assert() -> Result<()> {
|
||||
let value = pallas::Base::from(42);
|
||||
let token_id = pallas::Base::from(22);
|
||||
let value = 42;
|
||||
let token_id = pallas::Base::random(&mut OsRng);
|
||||
let value_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let token_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let serial = pallas::Base::random(&mut OsRng);
|
||||
@@ -517,7 +510,8 @@ mod tests {
|
||||
|
||||
let coin2 = {
|
||||
let coords = PublicKey::from_secret(secret).0.to_affine().coordinates().unwrap();
|
||||
let msg = [*coords.x(), *coords.y(), value, token_id, serial, coin_blind];
|
||||
let msg =
|
||||
[*coords.x(), *coords.y(), pallas::Base::from(value), token_id, serial, coin_blind];
|
||||
poseidon::Hash::<_, P128Pow5T3, ConstantLength<6>, 3, 2>::init().hash(msg)
|
||||
};
|
||||
|
||||
@@ -542,10 +536,10 @@ mod tests {
|
||||
let nullifier =
|
||||
poseidon::Hash::<_, P128Pow5T3, ConstantLength<2>, 3, 2>::init().hash(nullifier);
|
||||
|
||||
let value_commit = pedersen_commitment_scalar(mod_r_p(value), value_blind);
|
||||
let value_commit = pedersen_commitment_u64(value, value_blind);
|
||||
let value_coords = value_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let token_commit = pedersen_commitment_scalar(mod_r_p(token_id), token_blind);
|
||||
let token_commit = pedersen_commitment_base(token_id, token_blind);
|
||||
let token_coords = token_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let sig_pubkey = PublicKey::from_secret(sig_secret);
|
||||
@@ -565,7 +559,7 @@ mod tests {
|
||||
let circuit = BurnContract {
|
||||
secret_key: Value::known(secret.0),
|
||||
serial: Value::known(serial),
|
||||
value: Value::known(value),
|
||||
value: Value::known(pallas::Base::from(value)),
|
||||
token: Value::known(token_id),
|
||||
coin_blind: Value::known(coin_blind),
|
||||
value_blind: Value::known(value_blind),
|
||||
|
||||
@@ -1,23 +1,27 @@
|
||||
use halo2_gadgets::{
|
||||
ecc::{
|
||||
chip::{EccChip, EccConfig},
|
||||
FixedPoint, FixedPointShort, ScalarFixed, ScalarFixedShort,
|
||||
FixedPoint, FixedPointBaseField, FixedPointShort, ScalarFixed, ScalarFixedShort,
|
||||
},
|
||||
poseidon::{
|
||||
primitives as poseidon, Hash as PoseidonHash, Pow5Chip as PoseidonChip,
|
||||
Pow5Config as PoseidonConfig,
|
||||
},
|
||||
sinsemilla::chip::{SinsemillaChip, SinsemillaConfig},
|
||||
utilities::lookup_range_check::LookupRangeCheckConfig,
|
||||
};
|
||||
use halo2_proofs::{
|
||||
circuit::{floor_planner, AssignedCell, Layouter, Value},
|
||||
pasta::{pallas, Fp},
|
||||
plonk,
|
||||
plonk::{Advice, Circuit, Column, ConstraintSystem, Instance as InstanceColumn},
|
||||
};
|
||||
use pasta_curves::{pallas, Fp};
|
||||
|
||||
use crate::{
|
||||
crypto::constants::{OrchardFixedBases, OrchardFixedBasesFull, ValueCommitV},
|
||||
crypto::constants::{
|
||||
sinsemilla::{OrchardCommitDomains, OrchardHashDomains},
|
||||
NullifierK, OrchardFixedBases, OrchardFixedBasesFull, ValueCommitV,
|
||||
},
|
||||
zk::assign_free_advice,
|
||||
};
|
||||
|
||||
@@ -27,6 +31,8 @@ pub struct MintConfig {
|
||||
advices: [Column<Advice>; 10],
|
||||
ecc_config: EccConfig<OrchardFixedBases>,
|
||||
poseidon_config: PoseidonConfig<pallas::Base, 3, 2>,
|
||||
sinsemilla_config:
|
||||
SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
|
||||
}
|
||||
|
||||
impl MintConfig {
|
||||
@@ -89,7 +95,9 @@ impl Circuit<pallas::Base> for MintContract {
|
||||
meta.advice_column(),
|
||||
];
|
||||
|
||||
// Fixed columns for the Sinsemilla generator lookup table
|
||||
let table_idx = meta.lookup_table_column();
|
||||
let lookup = (table_idx, meta.lookup_table_column(), meta.lookup_table_column());
|
||||
|
||||
// Instance column used for public inputs
|
||||
let primary = meta.instance_column();
|
||||
@@ -147,7 +155,16 @@ impl Circuit<pallas::Base> for MintContract {
|
||||
rc_b,
|
||||
);
|
||||
|
||||
MintConfig { primary, advices, ecc_config, poseidon_config }
|
||||
let sinsemilla_config = SinsemillaChip::configure(
|
||||
meta,
|
||||
advices[..5].try_into().unwrap(),
|
||||
advices[6],
|
||||
ecc_lagrange_coeffs[0],
|
||||
lookup,
|
||||
range_check,
|
||||
);
|
||||
|
||||
MintConfig { primary, advices, ecc_config, poseidon_config, sinsemilla_config }
|
||||
}
|
||||
|
||||
fn synthesize(
|
||||
@@ -155,6 +172,9 @@ impl Circuit<pallas::Base> for MintContract {
|
||||
config: Self::Config,
|
||||
mut layouter: impl Layouter<pallas::Base>,
|
||||
) -> Result<(), plonk::Error> {
|
||||
// Load the Sinsemilla generator lookup table used by the whole circuit.
|
||||
SinsemillaChip::load(config.sinsemilla_config.clone(), &mut layouter)?;
|
||||
|
||||
let ecc_chip = config.ecc_chip();
|
||||
|
||||
let pub_x = assign_free_advice(
|
||||
@@ -227,8 +247,7 @@ impl Circuit<pallas::Base> for MintContract {
|
||||
|
||||
// v * G_1
|
||||
let (commitment, _) = {
|
||||
let value_commit_v = ValueCommitV;
|
||||
let value_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), value_commit_v);
|
||||
let value_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), ValueCommitV);
|
||||
let value = ScalarFixedShort::new(
|
||||
ecc_chip.clone(),
|
||||
layouter.namespace(|| "value"),
|
||||
@@ -244,8 +263,8 @@ impl Circuit<pallas::Base> for MintContract {
|
||||
layouter.namespace(|| "value_blind"),
|
||||
self.value_blind,
|
||||
)?;
|
||||
let value_commit_r = OrchardFixedBasesFull::ValueCommitR;
|
||||
let value_commit_r = FixedPoint::from_inner(ecc_chip.clone(), value_commit_r);
|
||||
let value_commit_r =
|
||||
FixedPoint::from_inner(ecc_chip.clone(), OrchardFixedBasesFull::ValueCommitR);
|
||||
value_commit_r.mul(layouter.namespace(|| "[value_blind] ValueCommitR"), rcv)?
|
||||
};
|
||||
|
||||
@@ -268,15 +287,9 @@ impl Circuit<pallas::Base> for MintContract {
|
||||
// Token commitment
|
||||
// ================
|
||||
// a * G_1
|
||||
let (commitment, _) = {
|
||||
let token_commit_v = ValueCommitV;
|
||||
let token_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), token_commit_v);
|
||||
let token = ScalarFixedShort::new(
|
||||
ecc_chip.clone(),
|
||||
layouter.namespace(|| "token"),
|
||||
(token, one),
|
||||
)?;
|
||||
token_commit_v.mul(layouter.namespace(|| "[token] ValueCommitV"), token)?
|
||||
let commitment = {
|
||||
let token_commit_v = FixedPointBaseField::from_inner(ecc_chip.clone(), NullifierK);
|
||||
token_commit_v.mul(layouter.namespace(|| "[token] NullifierK"), token)?
|
||||
};
|
||||
|
||||
// r_A * G_2
|
||||
@@ -286,8 +299,8 @@ impl Circuit<pallas::Base> for MintContract {
|
||||
layouter.namespace(|| "token_blind"),
|
||||
self.token_blind,
|
||||
)?;
|
||||
let token_commit_r = OrchardFixedBasesFull::ValueCommitR;
|
||||
let token_commit_r = FixedPoint::from_inner(ecc_chip, token_commit_r);
|
||||
let token_commit_r =
|
||||
FixedPoint::from_inner(ecc_chip, OrchardFixedBasesFull::ValueCommitR);
|
||||
token_commit_r.mul(layouter.namespace(|| "[token_blind] ValueCommitR"), rca)?
|
||||
};
|
||||
|
||||
@@ -318,12 +331,11 @@ mod tests {
|
||||
crypto::{
|
||||
keypair::PublicKey,
|
||||
proof::{ProvingKey, VerifyingKey},
|
||||
util::{mod_r_p, pedersen_commitment_scalar},
|
||||
util::{pedersen_commitment_base, pedersen_commitment_u64},
|
||||
Proof,
|
||||
},
|
||||
Result,
|
||||
};
|
||||
use group::{ff::Field, Curve};
|
||||
use halo2_gadgets::poseidon::{
|
||||
primitives as poseidon,
|
||||
primitives::{ConstantLength, P128Pow5T3},
|
||||
@@ -332,14 +344,17 @@ mod tests {
|
||||
circuit::Value,
|
||||
dev::{CircuitLayout, MockProver},
|
||||
};
|
||||
use pasta_curves::arithmetic::CurveAffine;
|
||||
use pasta_curves::{
|
||||
arithmetic::CurveAffine,
|
||||
group::{ff::Field, Curve},
|
||||
};
|
||||
use rand::rngs::OsRng;
|
||||
use std::time::Instant;
|
||||
|
||||
#[test]
|
||||
fn mint_circuit_assert() -> Result<()> {
|
||||
let value = pallas::Base::from(42);
|
||||
let token_id = pallas::Base::from(22);
|
||||
let value = 42;
|
||||
let token_id = pallas::Base::random(&mut OsRng);
|
||||
let value_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let token_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let serial = pallas::Base::random(&mut OsRng);
|
||||
@@ -347,13 +362,14 @@ mod tests {
|
||||
let public_key = PublicKey::random(&mut OsRng);
|
||||
let coords = public_key.0.to_affine().coordinates().unwrap();
|
||||
|
||||
let msg = [*coords.x(), *coords.y(), value, token_id, serial, coin_blind];
|
||||
let msg =
|
||||
[*coords.x(), *coords.y(), pallas::Base::from(value), token_id, serial, coin_blind];
|
||||
let coin = poseidon::Hash::<_, P128Pow5T3, ConstantLength<6>, 3, 2>::init().hash(msg);
|
||||
|
||||
let value_commit = pedersen_commitment_scalar(mod_r_p(value), value_blind);
|
||||
let value_commit = pedersen_commitment_u64(value, value_blind);
|
||||
let value_coords = value_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let token_commit = pedersen_commitment_scalar(mod_r_p(token_id), token_blind);
|
||||
let token_commit = pedersen_commitment_base(token_id, token_blind);
|
||||
let token_coords = token_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let public_inputs =
|
||||
@@ -362,7 +378,7 @@ mod tests {
|
||||
let circuit = MintContract {
|
||||
pub_x: Value::known(*coords.x()),
|
||||
pub_y: Value::known(*coords.y()),
|
||||
value: Value::known(value),
|
||||
value: Value::known(pallas::Base::from(value)),
|
||||
token: Value::known(token_id),
|
||||
serial: Value::known(serial),
|
||||
coin_blind: Value::known(coin_blind),
|
||||
@@ -375,13 +391,13 @@ mod tests {
|
||||
BitMapBackend::new("target/mint_circuit_layout.png", (3840, 2160)).into_drawing_area();
|
||||
root.fill(&WHITE).unwrap();
|
||||
let root = root.titled("Mint Circuit Layout", ("sans-serif", 60)).unwrap();
|
||||
CircuitLayout::default().render(8, &circuit, &root).unwrap();
|
||||
CircuitLayout::default().render(11, &circuit, &root).unwrap();
|
||||
|
||||
let prover = MockProver::run(8, &circuit, vec![public_inputs.clone()])?;
|
||||
let prover = MockProver::run(11, &circuit, vec![public_inputs.clone()])?;
|
||||
prover.assert_satisfied();
|
||||
|
||||
let now = Instant::now();
|
||||
let proving_key = ProvingKey::build(8, &circuit);
|
||||
let proving_key = ProvingKey::build(11, &circuit);
|
||||
println!("ProvingKey built [{:?}]", now.elapsed());
|
||||
let now = Instant::now();
|
||||
let proof = Proof::create(&proving_key, &[circuit], &public_inputs, &mut OsRng)?;
|
||||
@@ -389,7 +405,7 @@ mod tests {
|
||||
|
||||
let circuit = MintContract::default();
|
||||
let now = Instant::now();
|
||||
let verifying_key = VerifyingKey::build(8, &circuit);
|
||||
let verifying_key = VerifyingKey::build(11, &circuit);
|
||||
println!("VerifyingKey built [{:?}]", now.elapsed());
|
||||
let now = Instant::now();
|
||||
proof.verify(&verifying_key, &public_inputs)?;
|
||||
|
||||
@@ -15,7 +15,8 @@ use halo2_proofs::{
|
||||
plonk::{Advice, Assigned, Column},
|
||||
};
|
||||
|
||||
pub(in crate::zk) fn assign_free_advice<F: Field, V: Copy>(
|
||||
//pub(in crate::zk) fn assign_free_advice<F: Field, V: Copy>(
|
||||
pub fn assign_free_advice<F: Field, V: Copy>(
|
||||
mut layouter: impl Layouter<F>,
|
||||
column: Column<Advice>,
|
||||
value: Value<V>,
|
||||
|
||||
@@ -3,7 +3,7 @@ use darkfi::{
|
||||
keypair::{PublicKey, SecretKey},
|
||||
merkle_node::MerkleNode,
|
||||
proof::{ProvingKey, VerifyingKey},
|
||||
util::{mod_r_p, pedersen_commitment_scalar, pedersen_commitment_u64},
|
||||
util::{pedersen_commitment_base, pedersen_commitment_u64},
|
||||
Proof,
|
||||
},
|
||||
zk::{
|
||||
@@ -35,7 +35,7 @@ fn burn_proof() -> Result<()> {
|
||||
|
||||
// Witness values
|
||||
let value = 42;
|
||||
let token_id = pallas::Base::from(22);
|
||||
let token_id = pallas::Base::random(&mut OsRng);
|
||||
let value_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let token_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let serial = pallas::Base::random(&mut OsRng);
|
||||
@@ -94,7 +94,7 @@ fn burn_proof() -> Result<()> {
|
||||
let value_commit = pedersen_commitment_u64(value, value_blind);
|
||||
let value_coords = value_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let token_commit = pedersen_commitment_scalar(mod_r_p(token_id), token_blind);
|
||||
let token_commit = pedersen_commitment_base(token_id, token_blind);
|
||||
let token_coords = token_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let sig_pubkey = PublicKey::from_secret(sig_secret);
|
||||
|
||||
@@ -2,7 +2,7 @@ use darkfi::{
|
||||
crypto::{
|
||||
keypair::PublicKey,
|
||||
proof::{ProvingKey, VerifyingKey},
|
||||
util::{mod_r_p, pedersen_commitment_scalar, pedersen_commitment_u64},
|
||||
util::{pedersen_commitment_base, pedersen_commitment_u64},
|
||||
Proof,
|
||||
},
|
||||
zk::{
|
||||
@@ -33,7 +33,7 @@ fn mint_proof() -> Result<()> {
|
||||
|
||||
// Witness values
|
||||
let value = 42;
|
||||
let token_id = pallas::Base::from(22);
|
||||
let token_id = pallas::Base::random(&mut OsRng);
|
||||
let value_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let token_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let serial = pallas::Base::random(&mut OsRng);
|
||||
@@ -60,7 +60,7 @@ fn mint_proof() -> Result<()> {
|
||||
let value_commit = pedersen_commitment_u64(value, value_blind);
|
||||
let value_coords = value_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let token_commit = pedersen_commitment_scalar(mod_r_p(token_id), token_blind);
|
||||
let token_commit = pedersen_commitment_base(token_id, token_blind);
|
||||
let token_coords = token_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let public_inputs =
|
||||
|
||||
Reference in New Issue
Block a user