Skip to content

Commit

Permalink
A0-2084: Note gadget (#991)
Browse files Browse the repository at this point in the history
* One Merkle tree

* CLI for merge relation

* Order of vec elements

* Fix cliain

* Dot

* Rename circuit_utils to path_shape_var

* Note gadget

* Macro for boilerplate

* fmt

---------

Co-authored-by: Maciej Żelaszczyk <[email protected]>
Co-authored-by: maciejzelaszczyk <[email protected]>
Co-authored-by: Michal Swietek <[email protected]>
Co-authored-by: Michal Swietek <[email protected]>
  • Loading branch information
5 people authored Mar 14, 2023
1 parent b8f0fb6 commit 8e3643e
Show file tree
Hide file tree
Showing 13 changed files with 288 additions and 194 deletions.
1 change: 1 addition & 0 deletions bin/cliain/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion finality-aleph/src/sync/handler.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fmt::{Display, Error as FmtError, Formatter};

use crate::{
session::{SessionId, SessionBoundaryInfo, SessionPeriod},
session::{SessionBoundaryInfo, SessionId, SessionPeriod},
sync::{
data::{NetworkData, Request, State},
forest::{Error as ForestError, Forest, Interest},
Expand Down
1 change: 1 addition & 0 deletions relations/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions relations/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ ark-snark = { version = "^0.3.0", default-features = false }
ark-std = { version = "^0.3.0", default-features = false }
blake2 = { version = "0.9.2", default-features = false }
liminal-ark-relation-macro = { version = "0.1.1" }
paste = { version = "1.0.11" }

liminal-ark-poseidon = { path = "../poseidon", default-features = false, features = ["circuit"] }

Expand Down
4 changes: 2 additions & 2 deletions relations/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ pub use preimage::{
pub use relation::GetPublicInput;
pub use serialization::serialize;
pub use shielder::{
bytes_from_note, compute_note, compute_parent_hash, note_from_bytes, types::*,
DepositAndMergeRelationWithFullInput, DepositAndMergeRelationWithPublicInput,
bytes_from_note, compute_note, compute_parent_hash, note_from_bytes, note_var::NoteVarBuilder,
types::*, DepositAndMergeRelationWithFullInput, DepositAndMergeRelationWithPublicInput,
DepositAndMergeRelationWithoutInput, DepositRelationWithFullInput,
DepositRelationWithPublicInput, DepositRelationWithoutInput, MergeRelationWithFullInput,
MergeRelationWithPublicInput, MergeRelationWithoutInput, WithdrawRelationWithFullInput,
Expand Down
23 changes: 11 additions & 12 deletions relations/src/shielder/deposit.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use ark_r1cs_std::alloc::AllocVar;
use ark_relations::ns;
use liminal_ark_relation_macro::snark_relation;

use crate::{BackendNote, FrontendNote};
Expand All @@ -10,16 +8,17 @@ use crate::{BackendNote, FrontendNote};
/// `token_amount`, `trapdoor` and `nullifier`.
#[snark_relation]
mod relation {
use ark_r1cs_std::alloc::AllocationMode::{Input, Witness};

use crate::{
environment::FpVar,
shielder::{
convert_hash,
note::check_note,
types::{
BackendNullifier, BackendTokenAmount, BackendTokenId, BackendTrapdoor,
FrontendNullifier, FrontendTokenAmount, FrontendTokenId, FrontendTrapdoor,
},
},
NoteVarBuilder,
};

#[relation_object_definition]
Expand All @@ -39,14 +38,14 @@ mod relation {

#[circuit_definition]
fn generate_constraints() {
let note = FpVar::new_input(ns!(cs, "note"), || self.note())?;
let token_id = FpVar::new_input(ns!(cs, "token id"), || self.token_id())?;
let token_amount = FpVar::new_input(ns!(cs, "token amount"), || self.token_amount())?;

let trapdoor = FpVar::new_witness(ns!(cs, "trapdoor"), || self.trapdoor())?;
let nullifier = FpVar::new_witness(ns!(cs, "nullifier"), || self.nullifier())?;

check_note(&token_id, &token_amount, &trapdoor, &nullifier, &note)
let _note = NoteVarBuilder::new(cs)
.with_note(self.note(), Input)?
.with_token_id(self.token_id(), Input)?
.with_token_amount(self.token_amount(), Input)?
.with_trapdoor(self.trapdoor(), Witness)?
.with_nullifier(self.nullifier(), Witness)?
.build()?;
Ok(())
}
}

Expand Down
77 changes: 36 additions & 41 deletions relations/src/shielder/deposit_and_merge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,28 @@ use liminal_ark_relation_macro::snark_relation;
mod relation {
use core::ops::Add;

use ark_r1cs_std::{alloc::AllocVar, eq::EqGadget, fields::fp::FpVar};
use ark_r1cs_std::{
alloc::{
AllocVar,
AllocationMode::{Input, Witness},
},
eq::EqGadget,
fields::fp::FpVar,
};
use ark_relations::ns;

use crate::shielder::{
check_merkle_proof,
circuit_utils::PathShapeVar,
convert_hash, convert_vec,
note::check_note,
types::{
BackendLeafIndex, BackendMerklePath, BackendMerkleRoot, BackendNote, BackendNullifier,
BackendTokenAmount, BackendTokenId, BackendTrapdoor, FrontendLeafIndex,
FrontendMerklePath, FrontendMerkleRoot, FrontendNote, FrontendNullifier,
FrontendTokenAmount, FrontendTokenId, FrontendTrapdoor,
use crate::{
shielder::{
check_merkle_proof, convert_hash, convert_vec,
path_shape_var::PathShapeVar,
types::{
BackendLeafIndex, BackendMerklePath, BackendMerkleRoot, BackendNote,
BackendNullifier, BackendTokenAmount, BackendTokenId, BackendTrapdoor,
FrontendLeafIndex, FrontendMerklePath, FrontendMerkleRoot, FrontendNote,
FrontendNullifier, FrontendTokenAmount, FrontendTokenId, FrontendTrapdoor,
},
},
NoteVarBuilder,
};

#[relation_object_definition]
Expand Down Expand Up @@ -71,45 +79,32 @@ mod relation {
//------------------------------
// Check the old note arguments.
//------------------------------
let token_id = FpVar::new_input(ns!(cs, "token id"), || self.token_id())?;
let old_token_amount =
FpVar::new_witness(ns!(cs, "old token amount"), || self.old_token_amount())?;
let old_trapdoor = FpVar::new_witness(ns!(cs, "old trapdoor"), || self.old_trapdoor())?;
let old_nullifier = FpVar::new_input(ns!(cs, "old nullifier"), || self.old_nullifier())?;
let old_note = FpVar::new_witness(ns!(cs, "old note"), || self.old_note())?;

check_note(
&token_id,
&old_token_amount,
&old_trapdoor,
&old_nullifier,
&old_note,
)?;
let old_note = NoteVarBuilder::new(cs.clone())
.with_token_id(self.token_id(), Input)?
.with_token_amount(self.old_token_amount(), Witness)?
.with_trapdoor(self.old_trapdoor(), Witness)?
.with_nullifier(self.old_nullifier(), Input)?
.with_note(self.old_note(), Witness)?
.build()?;

//------------------------------
// Check the new note arguments.
//------------------------------
let new_token_amount =
FpVar::new_witness(ns!(cs, "new token amount"), || self.new_token_amount())?;
let new_trapdoor = FpVar::new_witness(ns!(cs, "new trapdoor"), || self.new_trapdoor())?;
let new_nullifier = FpVar::new_witness(ns!(cs, "new nullifier"), || self.new_nullifier())?;
let new_note = FpVar::new_input(ns!(cs, "new note"), || self.new_note())?;

check_note(
&token_id,
&new_token_amount,
&new_trapdoor,
&new_nullifier,
&new_note,
)?;
let new_note = NoteVarBuilder::new(cs.clone())
.with_token_id_var(old_note.token_id.clone())
.with_token_amount(self.new_token_amount(), Witness)?
.with_trapdoor(self.new_trapdoor(), Witness)?
.with_nullifier(self.new_nullifier(), Witness)?
.with_note(self.new_note(), Input)?
.build()?;

//----------------------------------
// Check the token values soundness.
//----------------------------------
let token_amount = FpVar::new_input(ns!(cs, "token amount"), || self.token_amount())?;
// some range checks for overflows?
let token_sum = token_amount.add(old_token_amount);
token_sum.enforce_equal(&new_token_amount)?;
let token_sum = token_amount.add(old_note.token_amount);
token_sum.enforce_equal(&new_note.token_amount)?;

//------------------------
// Check the merkle proof.
Expand All @@ -122,7 +117,7 @@ mod relation {
check_merkle_proof(
merkle_root,
path_shape,
old_note,
old_note.note,
self.merkle_path().cloned().unwrap_or_default(),
*self.max_path_len(),
cs,
Expand Down
113 changes: 46 additions & 67 deletions relations/src/shielder/merge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,28 @@ use liminal_ark_relation_macro::snark_relation;
mod relation {
use core::ops::Add;

use ark_r1cs_std::{alloc::AllocVar, eq::EqGadget, fields::fp::FpVar};
use ark_r1cs_std::{
alloc::{
AllocVar,
AllocationMode::{Input, Witness},
},
eq::EqGadget,
fields::fp::FpVar,
};
use ark_relations::ns;

use crate::shielder::{
check_merkle_proof,
circuit_utils::PathShapeVar,
convert_hash, convert_vec,
note::check_note,
types::{
BackendLeafIndex, BackendMerklePath, BackendMerkleRoot, BackendNote, BackendNullifier,
BackendTokenAmount, BackendTokenId, BackendTrapdoor, FrontendLeafIndex,
FrontendMerklePath, FrontendMerkleRoot, FrontendNote, FrontendNullifier,
FrontendTokenAmount, FrontendTokenId, FrontendTrapdoor,
use crate::{
shielder::{
check_merkle_proof, convert_hash, convert_vec,
path_shape_var::PathShapeVar,
types::{
BackendLeafIndex, BackendMerklePath, BackendMerkleRoot, BackendNote,
BackendNullifier, BackendTokenAmount, BackendTokenId, BackendTrapdoor,
FrontendLeafIndex, FrontendMerklePath, FrontendMerkleRoot, FrontendNote,
FrontendNullifier, FrontendTokenAmount, FrontendTokenId, FrontendTrapdoor,
},
},
NoteVarBuilder,
};

#[relation_object_definition]
Expand Down Expand Up @@ -82,76 +90,47 @@ mod relation {

#[circuit_definition]
fn generate_constraints() {
let token_id = FpVar::new_input(ns!(cs, "token id"), || self.token_id())?;
//------------------------------
// Check first old note arguments.
//------------------------------
let first_old_token_amount = FpVar::new_witness(ns!(cs, "first old token amount"), || {
self.first_old_token_amount()
})?;
let first_old_trapdoor =
FpVar::new_witness(ns!(cs, "first old trapdoor"), || self.first_old_trapdoor())?;
let first_old_nullifier = FpVar::new_input(ns!(cs, "first old nullifier"), || {
self.first_old_nullifier()
})?;
let first_old_note =
FpVar::new_witness(ns!(cs, "first old note"), || self.first_old_note())?;

check_note(
&token_id,
&first_old_token_amount,
&first_old_trapdoor,
&first_old_nullifier,
&first_old_note,
)?;
let first_old_note = NoteVarBuilder::new(cs.clone())
.with_token_id(self.token_id(), Input)?
.with_token_amount(self.first_old_token_amount(), Witness)?
.with_trapdoor(self.first_old_trapdoor(), Witness)?
.with_nullifier(self.first_old_nullifier(), Input)?
.with_note(self.first_old_note(), Witness)?
.build()?;

//------------------------------
// Check second old note arguments.
//------------------------------
let second_old_token_amount =
FpVar::new_witness(ns!(cs, "second old token amount"), || {
self.second_old_token_amount()
})?;
let second_old_trapdoor = FpVar::new_witness(ns!(cs, "second old trapdoor"), || {
self.second_old_trapdoor()
})?;
let second_old_nullifier = FpVar::new_input(ns!(cs, "second old nullifier"), || {
self.second_old_nullifier()
})?;
let second_old_note =
FpVar::new_witness(ns!(cs, "second old note"), || self.second_old_note())?;

check_note(
&token_id,
&second_old_token_amount,
&second_old_trapdoor,
&second_old_nullifier,
&second_old_note,
)?;
let second_old_note = NoteVarBuilder::new(cs.clone())
.with_token_id_var(first_old_note.token_id.clone())
.with_token_amount(self.second_old_token_amount(), Witness)?
.with_trapdoor(self.second_old_trapdoor(), Witness)?
.with_nullifier(self.second_old_nullifier(), Input)?
.with_note(self.second_old_note(), Witness)?
.build()?;

//------------------------------
// Check new note arguments.
//------------------------------
let new_token_amount =
FpVar::new_witness(ns!(cs, "new token amount"), || self.new_token_amount())?;
let new_trapdoor = FpVar::new_witness(ns!(cs, "new trapdoor"), || self.new_trapdoor())?;
let new_nullifier = FpVar::new_witness(ns!(cs, "new nullifier"), || self.new_nullifier())?;
let new_note = FpVar::new_input(ns!(cs, "new note"), || self.new_note())?;

check_note(
&token_id,
&new_token_amount,
&new_trapdoor,
&new_nullifier,
&new_note,
)?;
let new_note = NoteVarBuilder::new(cs.clone())
.with_token_id_var(first_old_note.token_id.clone())
.with_token_amount(self.new_token_amount(), Witness)?
.with_trapdoor(self.new_trapdoor(), Witness)?
.with_nullifier(self.new_nullifier(), Witness)?
.with_note(self.new_note(), Input)?
.build()?;

//----------------------------------
// Check token value soundness.
//----------------------------------
// some range checks for overflows?
let token_sum = first_old_token_amount.add(second_old_token_amount);
token_sum.enforce_equal(&new_token_amount)?;
let token_sum = first_old_note
.token_amount
.add(second_old_note.token_amount);
token_sum.enforce_equal(&new_note.token_amount)?;

//------------------------
// Check first merkle proof.
Expand All @@ -164,7 +143,7 @@ mod relation {
check_merkle_proof(
merkle_root.clone(),
first_path_shape,
first_old_note,
first_old_note.note,
self.first_merkle_path().cloned().unwrap_or_default(),
*self.max_path_len(),
cs.clone(),
Expand All @@ -180,7 +159,7 @@ mod relation {
check_merkle_proof(
merkle_root,
second_path_shape,
second_old_note,
second_old_note.note,
self.second_merkle_path().cloned().unwrap_or_default(),
*self.max_path_len(),
cs,
Expand Down
5 changes: 3 additions & 2 deletions relations/src/shielder/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
//! This module contains relations that are the core of the Shielder application: `deposit`, `deposit_and_merge` and
//! `withdraw`. It also exposes some functions and types that might be useful for input generation.
mod circuit_utils;
mod deposit;
mod deposit_and_merge;
mod merge;
mod note;
pub mod note_var;
mod path_shape_var;
pub mod types;
mod withdraw;

Expand Down Expand Up @@ -39,7 +40,7 @@ pub use withdraw::{

use crate::{
environment::{CircuitField, FpVar},
shielder::circuit_utils::PathShapeVar,
shielder::path_shape_var::PathShapeVar,
};

pub fn convert_hash(front: [u64; 4]) -> CircuitField {
Expand Down
Loading

0 comments on commit 8e3643e

Please sign in to comment.