Skip to content

Commit

Permalink
Merge branch 'master' into recipient
Browse files Browse the repository at this point in the history
  • Loading branch information
xevisalle authored Jun 3, 2024
2 parents 6785a43 + 46312f2 commit eaf2b71
Show file tree
Hide file tree
Showing 16 changed files with 173 additions and 122 deletions.
9 changes: 9 additions & 0 deletions circuits/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- Remove `ViewKey` from `TxOutputNote::new()` parameters [#191]
- Make `rng` the first param in `TxInputNote::new` [#189]
- Rename `crossover` to `deposit` [#190]

## [0.1.0] - 2024-05-22

### Added
Expand All @@ -23,6 +29,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Update `poseidon-merkle` to v0.6 [#179]

<!-- ISSUES -->
[#191]: https://github.com/dusk-network/phoenix/issues/191
[#190]: https://github.com/dusk-network/phoenix/issues/190
[#189]: https://github.com/dusk-network/phoenix/issues/189
[#179]: https://github.com/dusk-network/phoenix/issues/179
[#177]: https://github.com/dusk-network/phoenix/issues/177
[#171]: https://github.com/dusk-network/phoenix/issues/171
Expand Down
3 changes: 1 addition & 2 deletions circuits/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ dusk-jubjub = { version = "0.14", default-features = false }
poseidon-merkle = { version = "0.6", features = ["rkyv-impl", "zk", "size_32"] }
dusk-poseidon = { version = "0.39", features = ["zk"] }
jubjub-schnorr = { version = "0.4", features = ["zk"] }
rand_core = { version = "0.6", default-features = false }
rand = "0.8"
rand = { version = "0.8", default-features = false, features = ["std_rng"] }

[dev-dependencies]
ff = { version = "0.13", default-features = false }
Expand Down
2 changes: 1 addition & 1 deletion circuits/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ This library contains the implementation of the Phoenix-circuits, to prove, in z
2. Ownership: the sender holds the note secret key for every note that is about to be spent.
3. Nullification: the nullifier is calculated correctly.
4. Minting: the value commitment for the newly minted notes are computed correctly.
5. Balance integrity: the sum of the values of all spent notes is equal to the sum of the values of all minted notes + the gas fee + a crossover, where a crossover refers to funds being transfered to a contract.
5. Balance integrity: the sum of the values of all spent notes is equal to the sum of the values of all minted notes + the gas fee + a deposit, where a deposit refers to funds being transfered to a contract.
73 changes: 38 additions & 35 deletions circuits/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
// Copyright (c) DUSK NETWORK. All rights reserved.

use dusk_jubjub::{
JubJubScalar, GENERATOR, GENERATOR_NUMS, GENERATOR_NUMS_EXTENDED,
JubJubAffine, JubJubScalar, GENERATOR, GENERATOR_EXTENDED, GENERATOR_NUMS,
GENERATOR_NUMS_EXTENDED,
};
use dusk_plonk::prelude::*;
use dusk_poseidon::{Domain, Hash, HashGadget};
use jubjub_schnorr::{gadgets, SignatureDouble};
use poseidon_merkle::{zk::opening_gadget, Item, Opening, Tree};

use rand::rngs::StdRng;
use rand_core::{CryptoRng, RngCore, SeedableRng};
use rand::{CryptoRng, RngCore, SeedableRng};

extern crate alloc;
use alloc::vec::Vec;
Expand Down Expand Up @@ -54,11 +55,11 @@ struct WitnessTxInputNote {
impl<const H: usize> TxInputNote<H> {
/// Create a tx input note
pub fn new(
rng: &mut (impl RngCore + CryptoRng),
note: &Note,
merkle_opening: poseidon_merkle::Opening<(), H>,
sk: &SecretKey,
payload_hash: &BlsScalar,
rng: &mut (impl RngCore + CryptoRng),
) -> Result<crate::transaction::TxInputNote<H>, PhoenixError> {
let note_sk = sk.gen_note_sk(note);
let note_pk_p =
Expand Down Expand Up @@ -126,9 +127,9 @@ impl<const H: usize> TxInputNote<H> {
/// suitable for being introduced in the transfer circuit
#[derive(Debug, Clone)]
pub struct TxOutputNote {
pub(crate) value: u64,
pub(crate) value_commitment: JubJubAffine,
pub(crate) blinding_factor: JubJubScalar,
value: u64,
value_commitment: JubJubAffine,
blinding_factor: JubJubScalar,
}

#[derive(Debug, Clone)]
Expand All @@ -139,16 +140,18 @@ struct WitnessTxOutputNote {
}

impl TxOutputNote {
/// Create a tx output note
pub fn new(
note: &Note,
vk: &ViewKey,
) -> Result<crate::transaction::TxOutputNote, PhoenixError> {
Ok(crate::transaction::TxOutputNote {
value: note.value(Some(vk))?,
value_commitment: note.value_commitment().into(),
blinding_factor: note.blinding_factor(Some(vk))?,
})
/// Crate a new `TxOutputNote`.
pub fn new(value: u64, blinding_factor: JubJubScalar) -> Self {
let value_commitment = JubJubAffine::from(
(GENERATOR_EXTENDED * JubJubScalar::from(value))
+ (GENERATOR_NUMS_EXTENDED * blinding_factor),
);

Self {
value,
value_commitment,
blinding_factor,
}
}

fn append_to_circuit(
Expand Down Expand Up @@ -180,23 +183,22 @@ impl TxOutputNote {
/// correctly.
/// 5. Balance integrity: the sum of the values of all [`TxInputNote`] is equal
/// to the sum of the values of all [`TxOutputNote`] + the gas fee + a
/// crossover, where a crossover refers to funds being transfered to a
/// contract.
/// deposit, where a deposit refers to funds being transfered to a contract.
///
/// The gadget appends the following public input values to the circuit:
/// - `root`
/// - `[nullifier; I]`
/// - `[output_value_commitment; 2]`
/// - `max_fee`
/// - `crossover`
/// - `deposit`
fn nullify_gadget<const H: usize, const I: usize>(
composer: &mut Composer,
payload_hash: &Witness,
root: &BlsScalar,
tx_input_notes: &[TxInputNote<H>; I],
tx_output_notes: &[TxOutputNote; TX_OUTPUT_NOTES],
max_fee: u64,
crossover: u64,
deposit: u64,
) -> Result<(), Error> {
let root_pi = composer.append_public(*root);

Expand Down Expand Up @@ -304,16 +306,16 @@ fn nullify_gadget<const H: usize, const I: usize>(
}

let max_fee = composer.append_public(max_fee);
let crossover = composer.append_public(crossover);
let deposit = composer.append_public(deposit);

// SUM UP THE CROSSOVER AND THE MAX FEE
// SUM UP THE DEPOSIT AND THE MAX FEE
let constraint = Constraint::new()
.left(1)
.a(tx_output_sum)
.right(1)
.b(max_fee)
.fourth(1)
.d(crossover);
.d(deposit);
tx_output_sum = composer.gate_add(constraint);

// VERIFY BALANCE
Expand All @@ -329,7 +331,7 @@ pub struct TxCircuit<const H: usize, const I: usize> {
tx_output_notes: [TxOutputNote; TX_OUTPUT_NOTES],
payload_hash: BlsScalar,
root: BlsScalar,
crossover: u64,
deposit: u64,
max_fee: u64,
rp: RecipientParameters,
}
Expand All @@ -339,7 +341,6 @@ impl<const H: usize, const I: usize> Default for TxCircuit<H, I> {
let mut rng = StdRng::seed_from_u64(0xbeef);

let sk = SecretKey::random(&mut rng);
let vk = ViewKey::from(&sk);

let mut tree = Tree::<(), H>::new();
let payload_hash = BlsScalar::default();
Expand All @@ -355,26 +356,28 @@ impl<const H: usize, const I: usize> Default for TxCircuit<H, I> {
for _ in 0..I {
let merkle_opening = tree.opening(*note.pos()).expect("Tree read.");
let tx_input_note = TxInputNote::new(
&mut rng,
&note,
merkle_opening,
&sk,
&payload_hash,
&mut rng,
)
.expect("Note created properly.");

tx_input_notes.push(tx_input_note);
}

let tx_output_note_1 =
TxOutputNote::new(&note, &vk).expect("Note created properly.");
let tx_output_note_2 =
TxOutputNote::new(&note, &vk).expect("Note created properly.");
let tx_output_note_1 = TxOutputNote {
value: 0,
value_commitment: JubJubAffine::default(),
blinding_factor: JubJubScalar::default(),
};
let tx_output_note_2 = tx_output_note_1.clone();

let tx_output_notes = [tx_output_note_1, tx_output_note_2];

let root = BlsScalar::default();
let crossover = u64::default();
let deposit = u64::default();
let max_fee = u64::default();

let rp = RecipientParameters::default();
Expand All @@ -384,7 +387,7 @@ impl<const H: usize, const I: usize> Default for TxCircuit<H, I> {
tx_output_notes,
payload_hash,
root,
crossover,
deposit,
max_fee,
rp,
}
Expand All @@ -398,7 +401,7 @@ impl<const H: usize, const I: usize> TxCircuit<H, I> {
tx_output_notes: [TxOutputNote; TX_OUTPUT_NOTES],
payload_hash: BlsScalar,
root: BlsScalar,
crossover: u64,
deposit: u64,
max_fee: u64,
rp: RecipientParameters,
) -> Self {
Expand All @@ -407,7 +410,7 @@ impl<const H: usize, const I: usize> TxCircuit<H, I> {
tx_output_notes,
payload_hash,
root,
crossover,
deposit,
max_fee,
rp,
}
Expand All @@ -427,7 +430,7 @@ impl<const H: usize, const I: usize> Circuit for TxCircuit<H, I> {
&self.tx_input_notes,
&self.tx_output_notes,
self.max_fee,
self.crossover,
self.deposit,
)?;

// Prove correctess of the recipient encryption
Expand Down
19 changes: 12 additions & 7 deletions circuits/tests/elgamal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,20 @@ use dusk_plonk::prelude::*;
use ff::Field;
use phoenix_circuits::elgamal;
use phoenix_core::{PublicKey, SecretKey};
use rand_core::OsRng;
use rand::rngs::StdRng;
use rand::SeedableRng;

#[test]
fn test_elgamal_encrypt_and_decrypt() {
let sk = SecretKey::random(&mut OsRng);
let mut rng = StdRng::seed_from_u64(0xc0b);

let sk = SecretKey::random(&mut rng);
let pk = PublicKey::from(&sk);

let message = GENERATOR_EXTENDED * JubJubScalar::from(1234u64);

// Encrypt using a fresh random value 'r'
let r = JubJubScalar::random(&mut OsRng);
let r = JubJubScalar::random(&mut rng);
let (c1, c2) = elgamal::encrypt(pk.A(), &message, &r);

// Assert decryption
Expand Down Expand Up @@ -97,21 +100,23 @@ impl Circuit for ElGamalCircuit {

#[test]
fn test_elgamal_gadgets() {
let sk = SecretKey::random(&mut OsRng);
let mut rng = StdRng::seed_from_u64(0xc0b);

let sk = SecretKey::random(&mut rng);
let pk = PublicKey::from(&sk);

let message = GENERATOR_EXTENDED * JubJubScalar::from(1234u64);
let r = JubJubScalar::random(&mut OsRng);
let r = JubJubScalar::random(&mut rng);
let (c1, c2) = elgamal::encrypt(pk.A(), &message, &r);

let pp = PublicParameters::setup(1 << CAPACITY, &mut OsRng).unwrap();
let pp = PublicParameters::setup(1 << CAPACITY, &mut rng).unwrap();

let (prover, verifier) = Compiler::compile::<ElGamalCircuit>(&pp, LABEL)
.expect("failed to compile circuit");

let (proof, public_inputs) = prover
.prove(
&mut OsRng,
&mut rng,
&ElGamalCircuit::new(&pk.A(), &sk.a(), &message, &r, &c1, &c2),
)
.expect("failed to prove");
Expand Down
Loading

0 comments on commit eaf2b71

Please sign in to comment.