Skip to content

Commit a6eba3e

Browse files
committed
refactor(rln-cli): migrate to V3 types
1 parent 94e4dd2 commit a6eba3e

5 files changed

Lines changed: 227 additions & 232 deletions

File tree

rln-cli/Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ path = "src/examples/relay.rs"
1010
[[example]]
1111
name = "stateless"
1212
path = "src/examples/stateless.rs"
13-
required-features = ["stateless"]
1413

1514
[[example]]
1615
name = "multi_message_id"
@@ -27,7 +26,6 @@ clap = { version = "4.6.1", features = ["cargo", "derive", "env"] }
2726

2827
[features]
2928
default = ["rln/pmtree-ft", "rln/parallel"]
30-
stateless = ["rln/stateless", "rln/parallel"]
3129

3230
[package.metadata.docs.rs]
3331
all-features = true

rln-cli/src/examples/multi_message_id.rs

Lines changed: 73 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
use std::{
22
collections::HashMap,
3-
fs::File,
4-
io::{stdin, stdout, Read, Write},
5-
path::{Path, PathBuf},
3+
io::{stdin, stdout, Write},
64
};
75

86
use clap::{Parser, Subcommand};
97
use rln::prelude::{
10-
hash_to_field_le, keygen, poseidon_hash, recover_id_secret, Fr, IdSecret, PmtreeConfigBuilder,
11-
RLNProofValues, RLNWitnessInput, DEFAULT_TREE_DEPTH, RLN,
8+
default_graph_multi, default_zkey_multi, hash_to_field_le, keygen, poseidon_hash,
9+
ArkGroth16Backend, Fr, IdSecret, PmTree, PmTreeConfig, PoseidonHash, RLNBuilder,
10+
RLNProofValuesV3, RLNWitnessInputV3, RecoverSecret, Stateful, RLNV3,
1211
};
13-
use zerokit_utils::pm_tree::Mode;
12+
use zerokit_utils::merkle_tree::{Hasher, ZerokitMerkleProof, ZerokitMerkleTree};
1413

1514
const MESSAGE_LIMIT: u32 = 4;
1615

17-
const TREE_DEPTH: usize = DEFAULT_TREE_DEPTH;
16+
const TREE_DEPTH: usize = 20;
17+
18+
const MAX_OUT: usize = 4;
1819

1920
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
2021

@@ -60,39 +61,33 @@ impl Identity {
6061
}
6162

6263
struct RLNSystem {
63-
rln: RLN,
64-
used_nullifiers: HashMap<Fr, RLNProofValues>,
64+
rln: RLNV3<Stateful<PmTree>, ArkGroth16Backend>,
65+
used_nullifiers: HashMap<Fr, RLNProofValuesV3>,
6566
local_identities: HashMap<usize, Identity>,
6667
}
6768

6869
impl RLNSystem {
6970
fn new() -> Result<Self> {
70-
let mut resources: Vec<Vec<u8>> = Vec::new();
71-
let resources_path: PathBuf =
72-
format!("../rln/resources/tree_depth_{TREE_DEPTH}/multi_message_id/max_out_4").into();
73-
let filenames = ["rln_final.arkzkey", "graph.bin"];
74-
for filename in filenames {
75-
let fullpath = resources_path.join(Path::new(filename));
76-
let mut file = File::open(&fullpath)?;
77-
let metadata = std::fs::metadata(&fullpath)?;
78-
let mut output_buffer = vec![0; metadata.len() as usize];
79-
file.read_exact(&mut output_buffer)?;
80-
resources.push(output_buffer);
81-
}
82-
let tree_config = PmtreeConfigBuilder::new()
83-
.path("./database")
84-
.temporary(false)
85-
.cache_capacity(1073741824)
86-
.flush_every_ms(500)
87-
.mode(Mode::HighThroughput)
88-
.use_compression(false)
89-
.build()?;
90-
let rln = RLN::new_with_params(
71+
let pm_tree_config: PmTreeConfig = r#"{
72+
"path": "./database",
73+
"temporary": false,
74+
"cache_capacity": 1073741824,
75+
"flush_every_ms": 500,
76+
"mode": "HighThroughput",
77+
"use_compression": false,
78+
"tree_depth": 20
79+
}"#
80+
.parse()?;
81+
let pm_tree = <PmTree as ZerokitMerkleTree>::new(
9182
TREE_DEPTH,
92-
resources[0].clone(),
93-
resources[1].clone(),
94-
tree_config,
83+
PoseidonHash::default_leaf(),
84+
pm_tree_config,
9585
)?;
86+
let rln = RLNBuilder::stateful()
87+
.tree(pm_tree)
88+
.graph(default_graph_multi().clone())
89+
.zkey(default_zkey_multi().clone())
90+
.build();
9691
println!("RLN multi-message-id instance initialized successfully");
9792
Ok(RLNSystem {
9893
rln,
@@ -144,13 +139,8 @@ impl RLNSystem {
144139
Ok(Fr::from(id))
145140
})
146141
.collect::<Result<Vec<Fr>>>()?;
147-
if ids.len() != self.rln.max_out() {
148-
return Err(format!(
149-
"expected {} message IDs, got {}",
150-
self.rln.max_out(),
151-
ids.len()
152-
)
153-
.into());
142+
if ids.len() != MAX_OUT {
143+
return Err(format!("expected {} message IDs, got {}", MAX_OUT, ids.len()).into());
154144
}
155145
Ok(ids)
156146
}
@@ -164,10 +154,10 @@ impl RLNSystem {
164154
other => Err(format!("invalid selector value: '{other}'")),
165155
})
166156
.collect::<std::result::Result<Vec<bool>, String>>()?;
167-
if selector.len() != self.rln.max_out() {
157+
if selector.len() != MAX_OUT {
168158
return Err(format!(
169159
"expected {} selector values, got {}",
170-
self.rln.max_out(),
160+
MAX_OUT,
171161
selector.len()
172162
)
173163
.into());
@@ -182,76 +172,79 @@ impl RLNSystem {
182172
selector_used: Vec<bool>,
183173
signal: &str,
184174
external_nullifier: Fr,
185-
) -> Result<RLNProofValues> {
175+
) -> Result<RLNProofValuesV3> {
186176
let identity = match self.local_identities.get(&user_index) {
187177
Some(identity) => identity,
188178
None => return Err(format!("User {user_index} not found").into()),
189179
};
190180

191-
let (path_elements, identity_path_index) = self.rln.get_merkle_proof(user_index)?;
181+
let merkle_proof = self.rln.get_merkle_proof(user_index)?;
192182
let x = hash_to_field_le(signal.as_bytes());
193183

194-
let witness = RLNWitnessInput::new_multi(
195-
identity.identity_secret.clone(),
196-
Fr::from(MESSAGE_LIMIT),
197-
message_ids.clone(),
198-
path_elements,
199-
identity_path_index,
200-
x,
201-
external_nullifier,
202-
selector_used.clone(),
203-
)?;
184+
let witness = RLNWitnessInputV3::new_multi()
185+
.identity_secret(identity.identity_secret.clone())
186+
.user_message_limit(Fr::from(MESSAGE_LIMIT))
187+
.path_elements(merkle_proof.get_path_elements())
188+
.identity_path_index(merkle_proof.get_path_index())
189+
.x(x)
190+
.external_nullifier(external_nullifier)
191+
.message_ids(message_ids)
192+
.selector_used(selector_used.clone())
193+
.build()?;
204194

205-
let (proof, proof_values) = self.rln.generate_rln_proof(&witness)?;
195+
let (proof, proof_values) = self.rln.generate_proof(&witness)?;
206196
let active_count = selector_used.iter().filter(|&&s| s).count();
207197
println!("Proof generated successfully:");
208198
println!("+ User: {user_index}");
209-
println!(
210-
"+ Active message slots: {active_count}/{}",
211-
self.rln.max_out()
212-
);
199+
println!("+ Active message slots: {active_count}/{}", MAX_OUT);
213200
println!("+ Signal: {signal}");
214201

215-
let verified = self.rln.verify_rln_proof(&proof, &proof_values, &x)?;
202+
let verified = self.rln.verify(&proof, &proof_values)?;
216203
if verified {
217204
println!("Proof verified successfully");
218205
}
219206

220207
Ok(proof_values)
221208
}
222209

223-
fn check_nullifier(&mut self, proof_values: RLNProofValues) -> Result<()> {
224-
let nullifiers: Vec<Fr> = proof_values.nullifiers().to_vec();
225-
let selector: Vec<bool> = proof_values.selector_used().to_vec();
210+
fn check_nullifier(&mut self, proof_values: RLNProofValuesV3) -> Result<()> {
211+
if let (Some(nullifiers), Some(selector)) =
212+
(proof_values.nullifiers(), proof_values.selector_used())
213+
{
214+
for (i, (nullifier, active)) in nullifiers.iter().zip(selector.iter()).enumerate() {
215+
if !active {
216+
continue;
217+
}
226218

227-
for (i, (nullifier, active)) in nullifiers.iter().zip(selector.iter()).enumerate() {
228-
if !active {
229-
continue;
219+
if let Some(previous_proof_values) = self.used_nullifiers.get(nullifier) {
220+
self.handle_duplicate_nullifier(
221+
previous_proof_values.clone(),
222+
proof_values,
223+
i,
224+
)?;
225+
return Ok(());
226+
}
230227
}
231228

232-
if let Some(previous_proof_values) = self.used_nullifiers.get(nullifier) {
233-
self.handle_duplicate_nullifier(previous_proof_values.clone(), proof_values, i)?;
234-
return Ok(());
229+
for (nullifier, active) in nullifiers.iter().zip(selector.iter()) {
230+
if *active {
231+
self.used_nullifiers
232+
.insert(*nullifier, proof_values.clone());
233+
}
235234
}
235+
println!("Message verified and accepted");
236236
}
237237

238-
for (nullifier, active) in nullifiers.iter().zip(selector.iter()) {
239-
if *active {
240-
self.used_nullifiers
241-
.insert(*nullifier, proof_values.clone());
242-
}
243-
}
244-
println!("Message verified and accepted");
245238
Ok(())
246239
}
247240

248241
fn handle_duplicate_nullifier(
249242
&mut self,
250-
previous_proof_values: RLNProofValues,
251-
current_proof_values: RLNProofValues,
243+
previous_proof_values: RLNProofValuesV3,
244+
current_proof_values: RLNProofValuesV3,
252245
duplicated_slot: usize,
253246
) -> Result<()> {
254-
match recover_id_secret(&previous_proof_values, &current_proof_values) {
247+
match previous_proof_values.recover_secret(&current_proof_values) {
255248
Ok(leaked_identity_secret) => {
256249
if let Some((user_index, identity)) = self
257250
.local_identities
@@ -290,7 +283,7 @@ fn main() -> Result<()> {
290283
let external_nullifier = poseidon_hash(&[rln_epoch, rln_identifier]);
291284
println!("RLN Multi-Message-ID Example:");
292285
println!("Message Limit: {MESSAGE_LIMIT}");
293-
println!("Message Slots: {} - MAX_OUT", rln_system.rln.max_out());
286+
println!("Message Slots: 1 - {MAX_OUT}");
294287
println!("----------------------------------");
295288
println!();
296289
show_commands();

0 commit comments

Comments
 (0)