Skip to content

Commit

Permalink
Merge pull request #233 from anoma/xuyang/compose_note_commitment
Browse files Browse the repository at this point in the history
improve note commitment
boolean check `is_merkle_checked`
range(64bit) check `value`
  • Loading branch information
XuyangSong authored Nov 2, 2023
2 parents 9801cdb + c73af34 commit bb3b3bc
Show file tree
Hide file tree
Showing 7 changed files with 261 additions and 61 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ Cargo.lock

book/book

.DS_Store
.DS_Store

settings.json
18 changes: 16 additions & 2 deletions taiga_halo2/src/circuit/action_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ use halo2_proofs::{
};
use pasta_curves::pallas;

use crate::circuit::note_commitment::{NoteCommitChip, NoteCommitConfig};

#[derive(Clone, Debug)]
pub struct ActionConfig {
instances: Column<Instance>,
Expand All @@ -41,6 +43,7 @@ pub struct ActionConfig {
merkle_path_selector: Selector,
hash_to_curve_config: HashToCurveConfig,
blake2s_config: Blake2sConfig<pallas::Base>,
note_commit_config: NoteCommitConfig,
}

/// The Action circuit.
Expand Down Expand Up @@ -143,6 +146,13 @@ impl Circuit<pallas::Base> for ActionCircuit {

let blake2s_config = Blake2sConfig::configure(meta, advices);

let note_commit_config = NoteCommitChip::configure(
meta,
advices[0..3].try_into().unwrap(),
poseidon_config.clone(),
range_check,
);

Self::Config {
instances,
advices,
Expand All @@ -153,6 +163,7 @@ impl Circuit<pallas::Base> for ActionCircuit {
merkle_path_selector,
hash_to_curve_config,
blake2s_config,
note_commit_config,
}
}

Expand Down Expand Up @@ -185,13 +196,16 @@ impl Circuit<pallas::Base> for ActionCircuit {
// Construct a blake2s chip
let blake2s_chip = Blake2sChip::construct(config.blake2s_config);

// Construct a note_commit chip
let note_commit_chip = NoteCommitChip::construct(config.note_commit_config);

// Input note
// Check the input note commitment
let input_note_variables = check_input_note(
layouter.namespace(|| "check input note"),
config.advices,
config.instances,
config.poseidon_config.clone(),
note_commit_chip.clone(),
self.input_note,
ACTION_NF_PUBLIC_INPUT_ROW_IDX,
)?;
Expand All @@ -209,7 +223,7 @@ impl Circuit<pallas::Base> for ActionCircuit {
layouter.namespace(|| "check output note"),
config.advices,
config.instances,
config.poseidon_config,
note_commit_chip,
self.output_note,
input_note_variables.nf,
ACTION_OUTPUT_CM_PUBLIC_INPUT_ROW_IDX,
Expand Down
97 changes: 43 additions & 54 deletions taiga_halo2/src/circuit/integrity.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::circuit::{
gadgets::{assign_free_advice, assign_free_constant, poseidon_hash::poseidon_hash_gadget},
hash_to_curve::{hash_to_curve_circuit, HashToCurveConfig},
note_commitment::{note_commit, NoteCommitChip},
vp_circuit::{InputNoteVariables, NoteVariables, OutputNoteVariables},
};
use crate::constant::{TaigaFixedBases, TaigaFixedBasesFull, POSEIDON_TO_CURVE_INPUT_LEN};
Expand All @@ -9,6 +10,7 @@ use crate::utils::poseidon_to_curve;
use halo2_gadgets::{
ecc::{chip::EccChip, FixedPoint, NonIdentityPoint, Point, ScalarFixed, ScalarVar},
poseidon::Pow5Config as PoseidonConfig,
utilities::lookup_range_check::LookupRangeCheckConfig,
};
use halo2_proofs::{
circuit::{AssignedCell, Layouter, Value},
Expand All @@ -18,39 +20,6 @@ use pasta_curves::group::Curve;
use pasta_curves::pallas;
use std::ops::Neg;

#[allow(clippy::too_many_arguments)]
pub fn note_commitment_circuit(
mut layouter: impl Layouter<pallas::Base>,
poseidon_config: PoseidonConfig<pallas::Base, 3, 2>,
app_vp: AssignedCell<pallas::Base, pallas::Base>,
app_data_static: AssignedCell<pallas::Base, pallas::Base>,
app_data_dynamic: AssignedCell<pallas::Base, pallas::Base>,
nk_com: AssignedCell<pallas::Base, pallas::Base>,
rho: AssignedCell<pallas::Base, pallas::Base>,
psi: AssignedCell<pallas::Base, pallas::Base>,
value: AssignedCell<pallas::Base, pallas::Base>,
is_merkle_checked: AssignedCell<pallas::Base, pallas::Base>,
rcm: AssignedCell<pallas::Base, pallas::Base>,
) -> Result<AssignedCell<pallas::Base, pallas::Base>, Error> {
// TODO: compose the value and is_merkle_checked to one field in order to save one poseidon absorb
let poseidon_message = [
app_vp,
app_data_static,
app_data_dynamic,
nk_com,
rho,
psi,
is_merkle_checked,
value,
rcm,
];
poseidon_hash_gadget(
poseidon_config,
layouter.namespace(|| "note commitment"),
poseidon_message,
)
}

// cm is a field element
#[allow(clippy::too_many_arguments)]
pub fn nullifier_circuit(
Expand All @@ -75,8 +44,7 @@ pub fn check_input_note(
mut layouter: impl Layouter<pallas::Base>,
advices: [Column<Advice>; 10],
instances: Column<Instance>,
// PoseidonChip can not be cloned, use PoseidonConfig temporarily
poseidon_config: PoseidonConfig<pallas::Base, 3, 2>,
note_commit_chip: NoteCommitChip,
input_note: Note,
nf_row_idx: usize,
) -> Result<InputNoteVariables, Error> {
Expand All @@ -96,7 +64,7 @@ pub fn check_input_note(

// nk_com = Com_r(nk, zero)
let nk_com = poseidon_hash_gadget(
poseidon_config.clone(),
note_commit_chip.get_poseidon_config(),
layouter.namespace(|| "nk_com encoding"),
[nk_var.clone(), zero_constant],
)?;
Expand All @@ -122,11 +90,11 @@ pub fn check_input_note(
Value::known(input_note.get_app_data_static()),
)?;

// Witness value(u64)
let value = assign_free_advice(
layouter.namespace(|| "witness value"),
advices[0],
Value::known(pallas::Base::from(input_note.value)),
// Witness and range check the value(u64)
let value = value_range_check(
layouter.namespace(|| "value range check"),
note_commit_chip.get_lookup_config(),
input_note.value,
)?;

// Witness rho
Expand All @@ -151,16 +119,17 @@ pub fn check_input_note(
)?;

// Witness is_merkle_checked
// is_merkle_checked will be boolean-constrained in the note_commit.
let is_merkle_checked = assign_free_advice(
layouter.namespace(|| "witness is_merkle_checked"),
advices[0],
Value::known(pallas::Base::from(input_note.is_merkle_checked)),
)?;

// Check note commitment
let cm = note_commitment_circuit(
let cm = note_commit(
layouter.namespace(|| "note commitment"),
poseidon_config.clone(),
note_commit_chip.clone(),
app_vk.clone(),
app_data_static.clone(),
app_data_dynamic.clone(),
Expand All @@ -175,7 +144,7 @@ pub fn check_input_note(
// Generate nullifier
let nf = nullifier_circuit(
layouter.namespace(|| "Generate nullifier"),
poseidon_config,
note_commit_chip.get_poseidon_config(),
nk_var,
rho.clone(),
psi.clone(),
Expand Down Expand Up @@ -209,9 +178,7 @@ pub fn check_output_note(
mut layouter: impl Layouter<pallas::Base>,
advices: [Column<Advice>; 10],
instances: Column<Instance>,
// PoseidonChip can not be cloned, use PoseidonConfig temporarily
poseidon_config: PoseidonConfig<pallas::Base, 3, 2>,
// poseidon_chip: PoseidonChip<pallas::Base, 3, 2>,
note_commit_chip: NoteCommitChip,
output_note: Note,
old_nf: AssignedCell<pallas::Base, pallas::Base>,
cm_row_idx: usize,
Expand Down Expand Up @@ -244,11 +211,11 @@ pub fn check_output_note(
Value::known(output_note.get_app_data_static()),
)?;

// Witness value(u64)
let value = assign_free_advice(
layouter.namespace(|| "witness value"),
advices[0],
Value::known(pallas::Base::from(output_note.value)),
// Witness and range check the value(u64)
let value = value_range_check(
layouter.namespace(|| "value range check"),
note_commit_chip.get_lookup_config(),
output_note.value,
)?;

// Witness rcm
Expand All @@ -266,16 +233,17 @@ pub fn check_output_note(
)?;

// Witness is_merkle_checked
// is_merkle_checked will be boolean-constrained in the note_commit.
let is_merkle_checked = assign_free_advice(
layouter.namespace(|| "witness is_merkle_checked"),
advices[0],
Value::known(pallas::Base::from(output_note.is_merkle_checked)),
)?;

// Check note commitment
let cm = note_commitment_circuit(
let cm = note_commit(
layouter.namespace(|| "note commitment"),
poseidon_config.clone(),
note_commit_chip,
app_vk.clone(),
app_data_static.clone(),
app_data_dynamic.clone(),
Expand Down Expand Up @@ -426,6 +394,27 @@ pub fn compute_value_commitment(
commitment_v.add(layouter.namespace(|| "net value commitment"), &blind)
}

fn value_range_check<const K: usize>(
mut layouter: impl Layouter<pallas::Base>,
lookup_config: &LookupRangeCheckConfig<pallas::Base, K>,
value: u64,
) -> Result<AssignedCell<pallas::Base, pallas::Base>, Error> {
let zs = lookup_config.witness_check(
layouter.namespace(|| "6 * K(10) bits range check"),
Value::known(pallas::Base::from(value)),
6,
false,
)?;

lookup_config.copy_short_check(
layouter.namespace(|| "4 bits range check"),
zs[6].clone(),
4,
)?;

Ok(zs[0].clone())
}

#[test]
fn test_halo2_nullifier_circuit() {
use crate::circuit::gadgets::assign_free_advice;
Expand Down
1 change: 1 addition & 0 deletions taiga_halo2/src/circuit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub mod vp_circuit;
pub mod blake2s;
pub mod curve;
pub mod hash_to_curve;
pub mod note_commitment;
pub mod note_encryption_circuit;
mod vamp_ir_utils;
#[cfg(feature = "borsh")]
Expand Down
Loading

0 comments on commit bb3b3bc

Please sign in to comment.