Skip to content

Commit

Permalink
minor
Browse files Browse the repository at this point in the history
  • Loading branch information
xevisalle committed May 16, 2024
1 parent b5788b7 commit 1895e5d
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 111 deletions.
165 changes: 84 additions & 81 deletions circuits/src/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ use alloc::vec::Vec;

use phoenix_core::{Error as PhoenixError, Note, Ownable, SecretKey, ViewKey};

const OUTPUT: usize = 2;
const TX_OUTPUT_NOTES: usize = 2;

/// Struct representing a note willing to be spent, in a way
/// suitable for being introduced in the transfer circuit
#[derive(Debug, Clone)]
pub struct InputNote<const H: usize, const A: usize> {
pub struct TxInputNote<const H: usize, const A: usize> {
pub(crate) merkle_opening: Opening<(), H, A>,
pub(crate) note: Note,
pub(crate) note_pk_p: JubJubAffine,
Expand All @@ -36,7 +36,7 @@ pub struct InputNote<const H: usize, const A: usize> {
}

#[derive(Debug, Clone)]
struct WitnessInputNote {
struct WitnessTxInputNote {
note_pk: WitnessPoint,
note_pk_p: WitnessPoint,
note_type: Witness,
Expand All @@ -49,15 +49,15 @@ struct WitnessInputNote {
signature_r_p: WitnessPoint,
}

impl<const H: usize, const A: usize> InputNote<H, A> {
/// Create a circuit input note
impl<const H: usize, const A: usize> TxInputNote<H, A> {
/// Create a tx input note
pub fn new(
note: &Note,
merkle_opening: poseidon_merkle::Opening<(), H, A>,
sk: &SecretKey,
skeleteon_hash: BlsScalar,
rng: &mut (impl RngCore + CryptoRng),
) -> Result<crate::transfer::InputNote<H, A>, PhoenixError> {
) -> Result<crate::transfer::TxInputNote<H, A>, PhoenixError> {
let note_sk = sk.gen_note_sk(note);
let note_pk_p =
JubJubAffine::from(GENERATOR_NUMS_EXTENDED * note_sk.as_ref());
Expand All @@ -74,7 +74,7 @@ impl<const H: usize, const A: usize> InputNote<H, A> {

let signature = note_sk.sign_double(rng, skeleteon_hash);

Ok(crate::transfer::InputNote {
Ok(crate::transfer::TxInputNote {
merkle_opening,
note: note.clone(),
note_pk_p,
Expand All @@ -85,7 +85,7 @@ impl<const H: usize, const A: usize> InputNote<H, A> {
})
}

fn append_to_circuit(&self, composer: &mut Composer) -> WitnessInputNote {
fn append_to_circuit(&self, composer: &mut Composer) -> WitnessTxInputNote {
let nullifier = composer.append_public(self.nullifier);

let note_pk = composer
Expand All @@ -103,7 +103,7 @@ impl<const H: usize, const A: usize> InputNote<H, A> {
let signature_r = composer.append_point(self.signature.R());
let signature_r_p = composer.append_point(self.signature.R_prime());

WitnessInputNote {
WitnessTxInputNote {
note_pk,
note_pk_p,

Expand All @@ -124,52 +124,55 @@ impl<const H: usize, const A: usize> InputNote<H, A> {
/// Struct representing a note willing to be created, in a way
/// suitable for being introduced in the transfer circuit
#[derive(Debug, Clone)]
pub struct OutputNote {
pub struct TxOutputNote {
pub(crate) value: u64,
pub(crate) value_commitment: JubJubAffine,
pub(crate) blinding_factor: JubJubScalar,
}

#[derive(Debug, Clone)]
struct WitnessOutputNote {
struct WitnessTxOutputNote {
value: Witness,
value_commitment: WitnessPoint,
blinding_factor: Witness,
}

impl OutputNote {
/// Create a circuit output note
impl TxOutputNote {
/// Create a tx output note
pub fn new(
note: &Note,
vk: &ViewKey,
) -> Result<crate::transfer::OutputNote, PhoenixError> {
Ok(crate::transfer::OutputNote {
) -> Result<crate::transfer::TxOutputNote, PhoenixError> {
Ok(crate::transfer::TxOutputNote {
value: note.value(Some(vk))?,
value_commitment: note.value_commitment().into(),
blinding_factor: note.blinding_factor(Some(vk))?,
})
}

fn append_to_circuit(&self, composer: &mut Composer) -> WitnessOutputNote {
fn append_to_circuit(
&self,
composer: &mut Composer,
) -> WitnessTxOutputNote {
let value = composer.append_witness(self.value);
let value_commitment =
composer.append_public_point(self.value_commitment);
let blinding_factor = composer.append_witness(self.blinding_factor);

WitnessOutputNote {
WitnessTxOutputNote {
value,
value_commitment,
blinding_factor,
}
}
}

/// Transfer gadget expecting I input notes to be spent and O output
/// notes to be created.
/// Transfer gadget expecting I tx input notes to be spent, creating
/// TX_OUTPUT_NOTES = 2 tx output notes
pub fn gadget<const H: usize, const A: usize, const I: usize>(
composer: &mut Composer,
input_notes: &[InputNote<H, A>; I],
output_notes: &[OutputNote; OUTPUT],
tx_input_notes: &[TxInputNote<H, A>; I],
tx_output_notes: &[TxOutputNote; TX_OUTPUT_NOTES],
skeleton_hash: &BlsScalar,
root: &BlsScalar,
crossover: u64,
Expand All @@ -178,51 +181,51 @@ pub fn gadget<const H: usize, const A: usize, const I: usize>(
let skeleton_hash_pi = composer.append_public(*skeleton_hash);
let root_pi = composer.append_public(*root);

let mut input_notes_sum = Composer::ZERO;
let mut tx_input_notes_sum = Composer::ZERO;

// NULLIFY ALL INPUT NOTES
for input_note in input_notes {
// NULLIFY ALL TX INPUT NOTES
for tx_input_note in tx_input_notes {
// APPEND THE WITNESSES TO THE CIRCUIT
let w_input_note = input_note.append_to_circuit(composer);
let w_tx_input_note = tx_input_note.append_to_circuit(composer);

// VERIFY THE DOUBLE KEY SCHNORR SIGNATURE
gadgets::verify_signature_double(
composer,
w_input_note.signature_u,
w_input_note.signature_r,
w_input_note.signature_r_p,
w_input_note.note_pk,
w_input_note.note_pk_p,
w_tx_input_note.signature_u,
w_tx_input_note.signature_r,
w_tx_input_note.signature_r_p,
w_tx_input_note.note_pk,
w_tx_input_note.note_pk_p,
skeleton_hash_pi,
)?;

// COMPUTE AND ASSERT THE NULLIFIER
let nullifier = sponge::gadget(
composer,
&[
*w_input_note.note_pk_p.x(),
*w_input_note.note_pk_p.y(),
w_input_note.pos,
*w_tx_input_note.note_pk_p.x(),
*w_tx_input_note.note_pk_p.y(),
w_tx_input_note.pos,
],
);
composer.assert_equal(nullifier, w_input_note.nullifier);
composer.assert_equal(nullifier, w_tx_input_note.nullifier);

// PERFORM A RANGE CHECK ([0, 2^64 - 1]) ON THE VALUE OF THE NOTE
composer.component_range::<32>(w_input_note.value);
composer.component_range::<32>(w_tx_input_note.value);

// SUM UP ALL THE SPENT VALUES
// SUM UP ALL THE TX INPUT NOTE VALUES
let constraint = Constraint::new()
.left(1)
.a(input_notes_sum)
.a(tx_input_notes_sum)
.right(1)
.b(w_input_note.value);
input_notes_sum = composer.gate_add(constraint);
.b(w_tx_input_note.value);
tx_input_notes_sum = composer.gate_add(constraint);

// COMMIT TO THE VALUE OF THE NOTE
let pc_1 =
composer.component_mul_generator(w_input_note.value, GENERATOR)?;
let pc_1 = composer
.component_mul_generator(w_tx_input_note.value, GENERATOR)?;
let pc_2 = composer.component_mul_generator(
w_input_note.blinding_factor,
w_tx_input_note.blinding_factor,
GENERATOR_NUMS,
)?;
let value_commitment = composer.component_add_point(pc_1, pc_2);
Expand All @@ -231,50 +234,50 @@ pub fn gadget<const H: usize, const A: usize, const I: usize>(
let note_hash = sponge::gadget(
composer,
&[
w_input_note.note_type,
w_tx_input_note.note_type,
*value_commitment.x(),
*value_commitment.y(),
*w_input_note.note_pk.x(),
*w_input_note.note_pk.y(),
w_input_note.pos,
*w_tx_input_note.note_pk.x(),
*w_tx_input_note.note_pk.y(),
w_tx_input_note.pos,
],
);

// VERIFY THE MERKLE OPENING
let root =
opening_gadget(composer, &input_note.merkle_opening, note_hash);
opening_gadget(composer, &tx_input_note.merkle_opening, note_hash);
composer.assert_equal(root, root_pi);
}

let mut output_sum = Composer::ZERO;
let mut tx_output_sum = Composer::ZERO;

// COMMIT TO ALL OUTPUT NOTES
for output_note in output_notes {
// COMMIT TO ALL TX OUTPUT NOTES
for tx_output_note in tx_output_notes {
// APPEND THE WITNESSES TO THE CIRCUIT
let w_output_note = output_note.append_to_circuit(composer);
let w_tx_output_note = tx_output_note.append_to_circuit(composer);

// PERFORM A RANGE CHECK ([0, 2^64 - 1]) ON THE VALUE OF THE NOTE
composer.component_range::<32>(w_output_note.value);
composer.component_range::<32>(w_tx_output_note.value);

// SUM UP ALL THE CREATED NOTE VALUES
// SUM UP ALL THE TX OUTPUT NOTE VALUES
let constraint = Constraint::new()
.left(1)
.a(output_sum)
.a(tx_output_sum)
.right(1)
.b(w_output_note.value);
output_sum = composer.gate_add(constraint);
.b(w_tx_output_note.value);
tx_output_sum = composer.gate_add(constraint);

// COMMIT TO THE VALUE OF THE NOTE
let pc_1 =
composer.component_mul_generator(w_output_note.value, GENERATOR)?;
let pc_1 = composer
.component_mul_generator(w_tx_output_note.value, GENERATOR)?;
let pc_2 = composer.component_mul_generator(
w_output_note.blinding_factor,
w_tx_output_note.blinding_factor,
GENERATOR_NUMS,
)?;
let value_commitment = composer.component_add_point(pc_1, pc_2);

composer.assert_equal_point(
w_output_note.value_commitment,
w_tx_output_note.value_commitment,
value_commitment,
);
}
Expand All @@ -285,24 +288,24 @@ pub fn gadget<const H: usize, const A: usize, const I: usize>(
// SUM UP THE CROSSOVER AND THE MAX FEE
let constraint = Constraint::new()
.left(1)
.a(output_sum)
.a(tx_output_sum)
.right(1)
.b(max_fee)
.fourth(1)
.d(crossover);
output_sum = composer.gate_add(constraint);
tx_output_sum = composer.gate_add(constraint);

// VERIFY BALANCE
composer.assert_equal(input_notes_sum, output_sum);
composer.assert_equal(tx_input_notes_sum, tx_output_sum);

Ok(())
}

/// Declaration of the transfer circuit
#[derive(Debug)]
pub struct TransferCircuit<const H: usize, const A: usize, const I: usize> {
input_notes: [InputNote<H, A>; I],
output_notes: [OutputNote; OUTPUT],
tx_input_notes: [TxInputNote<H, A>; I],
tx_output_notes: [TxOutputNote; TX_OUTPUT_NOTES],
skeleton_hash: BlsScalar,
root: BlsScalar,
crossover: u64,
Expand All @@ -321,7 +324,7 @@ impl<const H: usize, const A: usize, const I: usize> Default
let mut tree = Tree::<(), H, A>::new();
let skeleton_hash = BlsScalar::default();

let mut input_notes = Vec::new();
let mut tx_input_notes = Vec::new();
let note = Note::empty();
let item = Item {
hash: note.hash(),
Expand All @@ -331,7 +334,7 @@ impl<const H: usize, const A: usize, const I: usize> Default

for _ in 0..I {
let merkle_opening = tree.opening(*note.pos()).expect("Tree read.");
let input_note = InputNote::new(
let tx_input_note = TxInputNote::new(
&note,
merkle_opening,
&sk,
Expand All @@ -340,23 +343,23 @@ impl<const H: usize, const A: usize, const I: usize> Default
)
.expect("Note created properly.");

input_notes.push(input_note);
tx_input_notes.push(tx_input_note);
}

let output_note_1 =
OutputNote::new(&note, &vk).expect("Note created properly.");
let output_note_2 =
OutputNote::new(&note, &vk).expect("Note created properly.");
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 output_notes = [output_note_1, output_note_2];
let tx_output_notes = [tx_output_note_1, tx_output_note_2];

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

Self {
input_notes: input_notes.try_into().unwrap(),
output_notes,
tx_input_notes: tx_input_notes.try_into().unwrap(),
tx_output_notes,
skeleton_hash,
root,
crossover,
Expand All @@ -368,16 +371,16 @@ impl<const H: usize, const A: usize, const I: usize> Default
impl<const H: usize, const A: usize, const I: usize> TransferCircuit<H, A, I> {
/// Create a new transfer circuit
pub fn new(
input_notes: [InputNote<H, A>; I],
output_notes: [OutputNote; OUTPUT],
tx_input_notes: [TxInputNote<H, A>; I],
tx_output_notes: [TxOutputNote; TX_OUTPUT_NOTES],
skeleton_hash: BlsScalar,
root: BlsScalar,
crossover: u64,
max_fee: u64,
) -> Self {
Self {
input_notes,
output_notes,
tx_input_notes,
tx_output_notes,
skeleton_hash,
root,
crossover,
Expand All @@ -392,8 +395,8 @@ impl<const H: usize, const A: usize, const I: usize> Circuit
fn circuit(&self, composer: &mut Composer) -> Result<(), Error> {
gadget::<H, A, I>(
composer,
&self.input_notes,
&self.output_notes,
&self.tx_input_notes,
&self.tx_output_notes,
&self.skeleton_hash,
&self.root,
self.crossover,
Expand Down
Loading

0 comments on commit 1895e5d

Please sign in to comment.