refactor(rln): Update Merkle tree initialization method (#30)

* refactor(rln): fix merkle tree initialization

* fix(rln): cargo fmt; cargo clippy
This commit is contained in:
G 2022-08-05 12:36:06 +02:00 committed by GitHub
parent cbb10efc10
commit 3378aed857
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 279 additions and 76 deletions

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,119 @@
{
"protocol": "groth16",
"curve": "bn128",
"nPublic": 6,
"vk_alpha_1": [
"1805378556360488226980822394597799963030511477964155500103132920745199284516",
"11990395240534218699464972016456017378439762088320057798320175886595281336136",
"1"
],
"vk_beta_2": [
[
"11031529986141021025408838211017932346992429731488270384177563837022796743627",
"16042159910707312759082561183373181639420894978640710177581040523252926273854"
],
[
"20112698439519222240302944148895052359035104222313380895334495118294612255131",
"19441583024670359810872018179190533814486480928824742448673677460151702019379"
],
[
"1",
"0"
]
],
"vk_gamma_2": [
[
"10857046999023057135944570762232829481370756359578518086990519993285655852781",
"11559732032986387107991004021392285783925812861821192530917403151452391805634"
],
[
"8495653923123431417604973247489272438418190587263600148770280649306958101930",
"4082367875863433681332203403145435568316851327593401208105741076214120093531"
],
[
"1",
"0"
]
],
"vk_delta_2": [
[
"1342791402398183550129987853701397066695422166542200371137242980909975744720",
"19885954793721639146517398722913034453263197732511169431324269951156805454588"
],
[
"16612518449808520746616592899100682320852224744311197908486719118388461103870",
"13039435290897389787786546960964558630619663289413586834851804020863949546009"
],
[
"1",
"0"
]
],
"vk_alphabeta_12": [
[
[
"5151991366823434428398919091000210787450832786814248297320989361921939794156",
"15735191313289001022885148627913534790382722933676436876510746491415970766821"
],
[
"3387907257437913904447588318761906430938415556102110876587455322225272831272",
"1998779853452712881084781956683721603875246565720647583735935725110674288056"
],
[
"14280074182991498185075387990446437410077692353432005297922275464876153151820",
"17092408446352310039633488224969232803092763095456307462247653153107223117633"
]
],
[
[
"4359046709531668109201634396816565829237358165496082832279660960675584351266",
"4511888308846208349307186938266411423935335853916317436093178288331845821336"
],
[
"11429499807090785857812316277335883295048773373068683863667725283965356423273",
"16232274853200678548795010078253506586114563833318973594428907292096178657392"
],
[
"18068999605870933925311275504102553573815570223888590384919752303726860800970",
"17309569111965782732372130116757295842160193489132771344011460471298173784984"
]
]
],
"IC": [
[
"15907620619058468322652190166474219459106695372760190199814463422116003944385",
"15752765921940703867480319151728055971288798043197983667046402260506178676501",
"1"
],
[
"12004081423498474638814710157503496372594892372197913146719480190853290407272",
"17759993271504587923309435837545182941635937261719294500288793819648071033469",
"1"
],
[
"878120019311612655450010384994897394984265086410869146105626241891073100410",
"17631186298933191134732246976686754514124819009836710500647157641262968661294",
"1"
],
[
"14710016919630225372037989028011020715054625029990218653012745498368446893907",
"2581293501049347486538806758240731445964309309490885835380825245889909387041",
"1"
],
[
"766327921864693063481261933507417084013182964450768912480746815296334678928",
"18104222034822903557262264275808261481286672296559910954337205847153944954509",
"1"
],
[
"8877686447180479408315100041907552504213694351585462004774320248566787828012",
"15836202093850379814510995758762098170932781831518064786308541653541698178373",
"1"
],
[
"19567388833538990982537236781224917793757180861915757860561618079730704818311",
"3535132838196675082818592669173684593624477421910576112671761297886253127546",
"1"
]
]
}

View File

@ -37,12 +37,12 @@
],
"vk_delta_2": [
[
"1342791402398183550129987853701397066695422166542200371137242980909975744720",
"19885954793721639146517398722913034453263197732511169431324269951156805454588"
"1948496782571164085469528023647105317580208688174386157591917599801657832035",
"20445814069256658101339037520922621162739470138213615104905368409238414511981"
],
[
"16612518449808520746616592899100682320852224744311197908486719118388461103870",
"13039435290897389787786546960964558630619663289413586834851804020863949546009"
"10024680869920840984813249386422727863826862577760330492647062850849851925340",
"10512156247842686783409460795717734694774542185222602679117887145206209285142"
],
[
"1",
@ -81,38 +81,38 @@
],
"IC": [
[
"15907620619058468322652190166474219459106695372760190199814463422116003944385",
"15752765921940703867480319151728055971288798043197983667046402260506178676501",
"18693301901828818437917730940595978397160482710354161265484535387752523310572",
"17985273354976640088538673802000794244421192643855111089693820179790551470769",
"1"
],
[
"12004081423498474638814710157503496372594892372197913146719480190853290407272",
"17759993271504587923309435837545182941635937261719294500288793819648071033469",
"21164641723988537620541455173278629777250883365474191521194244273980931825942",
"998385854410718613441067082771678946155853656328717326195057262123686425518",
"1"
],
[
"878120019311612655450010384994897394984265086410869146105626241891073100410",
"17631186298933191134732246976686754514124819009836710500647157641262968661294",
"21666968581672145768705229094968410656430989593283335488162701230986314747515",
"17996457608540683483506630273632100555125353447506062045735279661096094677264",
"1"
],
[
"14710016919630225372037989028011020715054625029990218653012745498368446893907",
"2581293501049347486538806758240731445964309309490885835380825245889909387041",
"20137761979695192602424300886442379728165712610493092740175904438282083668117",
"19184814924890679891263780109959113289320127263583260218200636509492157834679",
"1"
],
[
"766327921864693063481261933507417084013182964450768912480746815296334678928",
"18104222034822903557262264275808261481286672296559910954337205847153944954509",
"10943171273393803842589314082509655332154393332394322726077270895078286354146",
"10872472035685319847811233167729172672344935625121511932198535224727331126439",
"1"
],
[
"8877686447180479408315100041907552504213694351585462004774320248566787828012",
"15836202093850379814510995758762098170932781831518064786308541653541698178373",
"13049169779481227658517545034348883391527506091990880778783387628208561946597",
"10083689369261379027228809473568899816311684698866922944902456565434209079955",
"1"
],
[
"19567388833538990982537236781224917793757180861915757860561618079730704818311",
"3535132838196675082818592669173684593624477421910576112671761297886253127546",
"19633516378466409167014413361365552102431118630694133723053441455184566611083",
"8059525100726933978719058611146131904598011633549012007359165766216730722269",
"1"
]
]

View File

@ -23,10 +23,12 @@ const VK_FILENAME: &str = "verifying_key.json";
const WASM_FILENAME: &str = "rln.wasm";
// These parameters are used for tests
// Note that the circuit and keys in TEST_RESOURCES_FOLDER are compiled for Merkle trees of height 16 and 20 (including leaves level)
// Changing these parameters to other value than these twp defaults will cause zkSNARK proof verification to fail
//pub const TEST_TREE_HEIGHT: usize = 16;
//pub const TEST_RESOURCES_FOLDER: &str = "./resources/tree_height_16/";
// Note that the circuit and keys in TEST_RESOURCES_FOLDER are compiled for Merkle trees of height 15 and 19
// Changing these parameters to other values than these two defaults will cause zkSNARK proof verification to fail
//pub const TEST_TREE_HEIGHT: usize = 15;
//pub const TEST_RESOURCES_FOLDER: &str = "./resources/tree_height_15/";
//pub const TEST_TREE_HEIGHT: usize = 19;
//pub const TEST_RESOURCES_FOLDER: &str = "./resources/tree_height_19/";
pub const TEST_TREE_HEIGHT: usize = 20;
pub const TEST_RESOURCES_FOLDER: &str = "./resources/tree_height_20/";

View File

@ -450,8 +450,8 @@ mod test {
let mut expected_identity_path_index: Vec<u8> =
vec![1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
// We add the remaining elements for the case TEST_TREE_HEIGHT = 20
if TEST_TREE_HEIGHT == 20 {
// We add the remaining elements for the case TEST_TREE_HEIGHT = 19
if TEST_TREE_HEIGHT == 19 || TEST_TREE_HEIGHT == 20 {
expected_path_elements.append(&mut vec![
Field::from_str(
"0x22f98aa9ce704152ac17354914ad73ed1167ae6596af510aa5b3649325e06c92",
@ -473,6 +473,14 @@ mod test {
expected_identity_path_index.append(&mut vec![0, 0, 0, 0]);
}
if TEST_TREE_HEIGHT == 20 {
expected_path_elements.append(&mut vec![Field::from_str(
"0x1830ee67b5fb554ad5f63d4388800e1cfe78e310697d46e43c9ce36134f72cca",
)
.unwrap()]);
expected_identity_path_index.append(&mut vec![0]);
}
assert_eq!(path_elements, expected_path_elements);
assert_eq!(identity_path_index, expected_identity_path_index);

View File

@ -25,7 +25,7 @@ mod test {
use semaphore::{hash::Hash, identity::Identity, poseidon_hash, Field};
// Input generated with https://github.com/oskarth/zk-kit/commit/b6a872f7160c7c14e10a0ea40acab99cbb23c9a8
const WITNESS_JSON_16: &str = r#"
const WITNESS_JSON_15: &str = r#"
{
"identity_secret": "12825549237505733615964533204745049909430608936689388901883576945030025938736",
"path_elements": [
@ -69,7 +69,7 @@ mod test {
"#;
// Input generated with protocol::random_rln_witness
const WITNESS_JSON_20: &str = r#"
const WITNESS_JSON_19: &str = r#"
{
"identity_secret": "922538810348594125658702672067738675294669207539999802857585668079702330450",
"path_elements": [
@ -120,6 +120,60 @@ mod test {
}
"#;
const WITNESS_JSON_20: &str = r#"
{
"identity_secret": "13732353453861280511150022598793312186188599006979552959297495195757997428306",
"path_elements": [
"20463525608687844300981085488128968694844212760055234622292326942405619575964",
"8040856403709217901175408904825741112286158901303127670929462145501210871313",
"3776499751255585163563840252112871568402966629435152937692711318702338789837",
"19415813252626942110541463414404411443562242499365750694284604341271149125679",
"19414720788761208006634240390286942738242262010168559813148115573784354129237",
"17680594732844291740094158892269696200077963275550625226493856898849422516043",
"16009199741350632715210088346611798597033333293348807000623441780059543674510",
"18743496911007535170857676824393811326863602477260615792503039058813338644738",
"1029572792321380246989475723806770724699749375691788486434716005338938722216",
"21713138150151063186050010182615713685603650963220209951496401043119768920892",
"6713732504049401389983008178456811894856018247924860823028704114266363984580",
"2746686888799473963221285145390361693256731812094259845879519459924507786594",
"18620748467731297359505500266677881218553438497271819903304075323783392031715",
"2446201221122671119406471414204229600430018713181038717206670749886932158104",
"12037171942017611311954851302868199608036334625783560875426350283156617524597",
"21798743392351780927808323348278035105395367759688979232116905142049921734349",
"17450230289417496971557215666910229260621413088991137405744457922069827319039",
"20936854099128086256353520300046664152516566958630447858438908748907198510485",
"13513344965831154386658059617477268600255664386844920822248038939666265737046",
"15546319496880899251450021422131511560001766832580480193115646510655765306630"
],
"identity_path_index": [
0,
1,
0,
0,
1,
1,
0,
0,
1,
1,
0,
0,
0,
1,
0,
1,
1,
0,
0,
0
],
"x": "18073935665561339809445069958310044423750771681863480888589546877024349720547",
"epoch": "0x147e4c23a43a1ddca78d94bcd28147f62ca74b3dc7e56bb0a314a954b9f0e567",
"rln_identifier": "2193983000213424579594329476781986065965849144986973472766961413131458022566"
}
"#;
#[test]
// We test Merkle Tree generation, proofs and verification
fn test_merkle_proof() {
@ -140,7 +194,7 @@ mod test {
// We check correct computation of the root
let root = tree.root();
if TEST_TREE_HEIGHT == 16 {
if TEST_TREE_HEIGHT == 15 {
assert_eq!(
root,
Field::from_str(
@ -148,7 +202,7 @@ mod test {
)
.unwrap()
);
} else if TEST_TREE_HEIGHT == 20 {
} else if TEST_TREE_HEIGHT == 19 {
assert_eq!(
root,
Field::from_str(
@ -156,6 +210,14 @@ mod test {
)
.unwrap()
);
} else if TEST_TREE_HEIGHT == 20 {
assert_eq!(
root,
Field::from_str(
"0x0c33d9be0ca0dd96c64d92107886de4235108e0fee203bb044ac4ee210a3dfea"
)
.unwrap()
);
}
let merkle_proof = tree.proof(leaf_index).expect("proof should exist");
@ -201,7 +263,7 @@ mod test {
vec![1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
// We add the remaining elements for the case TEST_TREE_HEIGHT = 20
if TEST_TREE_HEIGHT == 20 {
if TEST_TREE_HEIGHT == 19 || TEST_TREE_HEIGHT == 20 {
expected_path_elements.append(&mut vec![
Field::from_str(
"0x22f98aa9ce704152ac17354914ad73ed1167ae6596af510aa5b3649325e06c92",
@ -223,6 +285,14 @@ mod test {
expected_identity_path_index.append(&mut vec![0, 0, 0, 0]);
}
if TEST_TREE_HEIGHT == 20 {
expected_path_elements.append(&mut vec![Field::from_str(
"0x1830ee67b5fb554ad5f63d4388800e1cfe78e310697d46e43c9ce36134f72cca",
)
.unwrap()]);
expected_identity_path_index.append(&mut vec![0]);
}
assert_eq!(path_elements, expected_path_elements);
assert_eq!(identity_path_index, expected_identity_path_index);
@ -241,8 +311,10 @@ mod test {
// We compute witness from the json input example
let mut witness_json: &str = "";
if TEST_TREE_HEIGHT == 16 {
witness_json = WITNESS_JSON_16;
if TEST_TREE_HEIGHT == 15 {
witness_json = WITNESS_JSON_15;
} else if TEST_TREE_HEIGHT == 19 {
witness_json = WITNESS_JSON_19;
} else if TEST_TREE_HEIGHT == 20 {
witness_json = WITNESS_JSON_20;
}
@ -311,8 +383,10 @@ mod test {
// We test witness serialization
let mut witness_json: &str = "";
if TEST_TREE_HEIGHT == 16 {
witness_json = WITNESS_JSON_16;
if TEST_TREE_HEIGHT == 15 {
witness_json = WITNESS_JSON_15;
} else if TEST_TREE_HEIGHT == 19 {
witness_json = WITNESS_JSON_19;
} else if TEST_TREE_HEIGHT == 20 {
witness_json = WITNESS_JSON_20;
}

View File

@ -27,10 +27,10 @@ pub trait Hasher {
/// Merkle tree with all leaf and intermediate hashes stored
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct MerkleTree<H: Hasher> {
/// Depth of the tree, # of layers including leaf layer
depth: usize,
/// total number of levels of the tree, i.e. # of layers including pre-images layer of tree leaves
levels: usize,
/// Hash value of empty subtrees of given depth, starting at leaf level
/// Hash value of empty subtrees of given levels, starting at leaf level
empty: Vec<H::Hash>,
/// Hash values of tree nodes and leaves, breadth first order
@ -70,7 +70,7 @@ const fn first_child(index: usize) -> usize {
(index << 1) + 1
}
const fn depth(index: usize) -> usize {
const fn levels(index: usize) -> usize {
// `n.next_power_of_two()` will return `n` iff `n` is a power of two.
// The extra offset corrects this.
(index + 2).next_power_of_two().trailing_zeros() as usize - 1
@ -78,12 +78,13 @@ const fn depth(index: usize) -> usize {
impl<H: Hasher> MerkleTree<H> {
/// Creates a new `MerkleTree`
/// * `depth` - The depth of the tree, including the root. This is 1 greater
/// than the `treeLevels` argument to the Semaphore contract.
pub fn new(depth: usize, initial_leaf: H::Hash) -> Self {
/// tree_height - the height of the tree made only of hash nodes. 2^tree_height is the maximum number of leaves hash nodes
pub fn new(tree_height: usize, initial_leaf: H::Hash) -> Self {
// total number of levels of the tree, i.e. # of layers including pre-images layer of tree leaves, thus equal to tree_height+1
let levels = tree_height + 1;
// Compute empty node values, leaf to root
let empty = successors(Some(initial_leaf), |prev| Some(H::hash_node(prev, prev)))
.take(depth)
.take(levels)
.collect::<Vec<_>>();
// Compute node values
@ -91,15 +92,15 @@ impl<H: Hasher> MerkleTree<H> {
.iter()
.rev()
.enumerate()
.flat_map(|(depth, hash)| repeat(hash).take(1 << depth))
.flat_map(|(levels, hash)| repeat(hash).take(1 << levels))
.cloned()
.collect::<Vec<_>>();
debug_assert!(nodes.len() == (1 << depth) - 1);
debug_assert!(nodes.len() == (1 << levels) - 1);
let next_index = 0;
Self {
depth,
levels,
empty,
nodes,
next_index,
@ -108,7 +109,7 @@ impl<H: Hasher> MerkleTree<H> {
#[must_use]
pub fn num_leaves(&self) -> usize {
self.depth
self.levels
.checked_sub(1)
.map(|n| 1 << n)
.unwrap_or_default()
@ -139,7 +140,7 @@ impl<H: Hasher> MerkleTree<H> {
}
fn update_nodes(&mut self, start: usize, end: usize) {
debug_assert_eq!(depth(start), depth(end));
debug_assert_eq!(levels(start), levels(end));
if let (Some(start), Some(end)) = (parent(start), parent(end)) {
for parent in start..=end {
let child = first_child(parent);
@ -155,7 +156,7 @@ impl<H: Hasher> MerkleTree<H> {
return None;
}
let mut index = self.num_leaves() + leaf - 1;
let mut path = Vec::with_capacity(self.depth);
let mut path = Vec::with_capacity(self.levels);
while let Some(parent) = parent(index) {
// Add proof for node at index to parent
path.push(match index & 1 {
@ -276,16 +277,16 @@ pub mod test {
assert_eq!(parent(6), Some(2));
assert_eq!(first_child(0), 1);
assert_eq!(first_child(2), 5);
assert_eq!(depth(0), 0);
assert_eq!(depth(1), 1);
assert_eq!(depth(2), 1);
assert_eq!(depth(3), 2);
assert_eq!(depth(6), 2);
assert_eq!(levels(0), 0);
assert_eq!(levels(1), 1);
assert_eq!(levels(2), 1);
assert_eq!(levels(3), 2);
assert_eq!(levels(6), 2);
}
#[test]
fn test_root() {
let mut tree = MerkleTree::<Keccak256>::new(3, [0; 32]);
let mut tree = MerkleTree::<Keccak256>::new(2, [0; 32]);
assert_eq!(
tree.root(),
hex!("b4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30")
@ -326,7 +327,7 @@ pub mod test {
#[test]
fn test_proof() {
let mut tree = MerkleTree::<Keccak256>::new(3, [0; 32]);
let mut tree = MerkleTree::<Keccak256>::new(2, [0; 32]);
tree.set(
0,
hex!("0000000000000000000000000000000000000000000000000000000000000001"),
@ -358,7 +359,7 @@ pub mod test {
#[test]
fn test_position() {
let mut tree = MerkleTree::<Keccak256>::new(3, [0; 32]);
let mut tree = MerkleTree::<Keccak256>::new(2, [0; 32]);
tree.set(
0,
hex!("0000000000000000000000000000000000000000000000000000000000000001"),

View File

@ -267,9 +267,7 @@ pub fn random_rln_witness(tree_height: usize) -> RLNWitnessInput {
let mut path_elements: Vec<Field> = Vec::new();
let mut identity_path_index: Vec<u8> = Vec::new();
// In semaphore's poseidon_tree, the leaves level is counted in tree_height.
// This means that a merkle proof consists of tree_height-1 field elements
for _ in 0..tree_height - 1 {
for _ in 0..tree_height {
path_elements.push(hash_to_field(&rng.gen::<[u8; 32]>()));
identity_path_index.push(rng.gen_range(0..2) as u8);
}
@ -295,15 +293,6 @@ pub fn proof_values_from_witness(rln_witness: &RLNWitnessInput) -> RLNProofValue
let nullifier = poseidon_hash(&[a_1, rln_witness.rln_identifier]);
// Merkle tree root computations
let mut root = poseidon_hash(&[rln_witness.identity_secret]);
for i in 0..rln_witness.identity_path_index.len() {
if rln_witness.identity_path_index[i] == 0 {
root = poseidon_hash(&[root, rln_witness.path_elements[i]]);
} else {
root = poseidon_hash(&[rln_witness.path_elements[i], root]);
}
}
let root = compute_tree_root(
&rln_witness.identity_secret,
&rln_witness.path_elements,

View File

@ -219,12 +219,6 @@ impl RLN<'_> {
let (rln_witness, _) = proof_inputs_to_rln_witness(&mut self.tree, &witness_byte);
let proof_values = proof_values_from_witness(&rln_witness);
/*
if self.witness_calculator.is_none() {
self.witness_calculator = CIRCOM(&self.resources_folder);
}
*/
let proof = generate_proof(
self.witness_calculator,
self.proving_key.as_ref().unwrap(),
@ -429,7 +423,7 @@ mod test {
rln.get_root(&mut buffer).unwrap();
let (root, _) = bytes_le_to_field(&buffer.into_inner());
if TEST_TREE_HEIGHT == 16 {
if TEST_TREE_HEIGHT == 15 {
assert_eq!(
root,
Field::from_str(
@ -437,7 +431,7 @@ mod test {
)
.unwrap()
);
} else if TEST_TREE_HEIGHT == 20 {
} else if TEST_TREE_HEIGHT == 19 {
assert_eq!(
root,
Field::from_str(
@ -445,6 +439,14 @@ mod test {
)
.unwrap()
);
} else if TEST_TREE_HEIGHT == 20 {
assert_eq!(
root,
Field::from_str(
"0x0c33d9be0ca0dd96c64d92107886de4235108e0fee203bb044ac4ee210a3dfea"
)
.unwrap()
);
}
// We check correct computation of merkle proof
@ -493,7 +495,7 @@ mod test {
vec![1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
// We add the remaining elements for the case TEST_TREE_HEIGHT = 20
if TEST_TREE_HEIGHT == 20 {
if TEST_TREE_HEIGHT == 19 || TEST_TREE_HEIGHT == 20 {
expected_path_elements.append(&mut vec![
Field::from_str(
"0x22f98aa9ce704152ac17354914ad73ed1167ae6596af510aa5b3649325e06c92",
@ -515,6 +517,14 @@ mod test {
expected_identity_path_index.append(&mut vec![0, 0, 0, 0]);
}
if TEST_TREE_HEIGHT == 20 {
expected_path_elements.append(&mut vec![Field::from_str(
"0x1830ee67b5fb554ad5f63d4388800e1cfe78e310697d46e43c9ce36134f72cca",
)
.unwrap()]);
expected_identity_path_index.append(&mut vec![0]);
}
assert_eq!(path_elements, expected_path_elements);
assert_eq!(identity_path_index, expected_identity_path_index);