Files
zerokit/rln-wasm/tests/utils.rs
Vinh Trịnh 77a8d28965 feat: unify RLN types, refactor public APIs, add full (de)serialization, align FFI/WASM/APIs, simplify errors, update docs/examples, and clean up zerokit (#355)
# Changes

- Unified the `RLN` struct and core protocol types across public, FFI,
and WASM so everything works consistently.
- Fully refactored `protocol.rs` and `public.rs` to clean up the API
surface and make the flow easier to work with.
- Added (de)serialization for `RLN_Proof` and `RLN_ProofValues`, and
matched all C, Nim, WASM, and Node.js examples.
- Aligned FFI and WASM behavior, added missing APIs, and standardized
how witness are created and passed around.
- Reworked the error types, added clearer verification messages, and
simplified the overall error structure.
- Updated variable names, README, Rust docs, and examples across the
repo, updated outdated RLN RFC link.
- Refactored `rln-cli` to use the new public API, removed
serialize-based cli example, and dropped the `eyre` crate.
- Bumped dependencies, fixed CI, fixed `+atomic` flags for latest
nightly Rust and added `Clippy.toml` for better fmt.
- Added a `prelude.rs` file for easier use, cleaned up public access for
types and types import across zerokit modules.
- Separated keygen, proof handling, slashing logic, and witness into
protocol folder.
2025-12-09 19:03:04 +07:00

223 lines
8.0 KiB
Rust

#![cfg(target_arch = "wasm32")]
#[cfg(test)]
mod test {
use std::assert_eq;
use ark_std::rand::thread_rng;
use js_sys::Uint8Array;
use rand::Rng;
use rln::prelude::*;
use rln_wasm::{ExtendedIdentity, Hasher, Identity, VecWasmFr, WasmFr};
use wasm_bindgen_test::wasm_bindgen_test;
#[wasm_bindgen_test]
fn test_keygen_wasm() {
let identity = Identity::generate();
let identity_secret = *identity.get_secret_hash();
let id_commitment = *identity.get_commitment();
assert_ne!(identity_secret, Fr::from(0u8));
assert_ne!(id_commitment, Fr::from(0u8));
let arr = identity.to_array();
assert_eq!(arr.length(), 2);
assert_eq!(*arr.get(0).unwrap(), identity_secret);
assert_eq!(*arr.get(1).unwrap(), id_commitment);
}
#[wasm_bindgen_test]
fn test_extended_keygen_wasm() {
let identity = ExtendedIdentity::generate();
let identity_trapdoor = *identity.get_trapdoor();
let identity_nullifier = *identity.get_nullifier();
let identity_secret = *identity.get_secret_hash();
let id_commitment = *identity.get_commitment();
assert_ne!(identity_trapdoor, Fr::from(0u8));
assert_ne!(identity_nullifier, Fr::from(0u8));
assert_ne!(identity_secret, Fr::from(0u8));
assert_ne!(id_commitment, Fr::from(0u8));
let arr = identity.to_array();
assert_eq!(arr.length(), 4);
assert_eq!(*arr.get(0).unwrap(), identity_trapdoor);
assert_eq!(*arr.get(1).unwrap(), identity_nullifier);
assert_eq!(*arr.get(2).unwrap(), identity_secret);
assert_eq!(*arr.get(3).unwrap(), id_commitment);
}
#[wasm_bindgen_test]
fn test_seeded_keygen_wasm() {
let seed_bytes: Vec<u8> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let seed = Uint8Array::from(&seed_bytes[..]);
let identity = Identity::generate_seeded(&seed);
let identity_secret = *identity.get_secret_hash();
let id_commitment = *identity.get_commitment();
let expected_identity_secret_seed_bytes = str_to_fr(
"0x766ce6c7e7a01bdf5b3f257616f603918c30946fa23480f2859c597817e6716",
16,
)
.unwrap();
let expected_id_commitment_seed_bytes = str_to_fr(
"0xbf16d2b5c0d6f9d9d561e05bfca16a81b4b873bb063508fae360d8c74cef51f",
16,
)
.unwrap();
assert_eq!(identity_secret, expected_identity_secret_seed_bytes);
assert_eq!(id_commitment, expected_id_commitment_seed_bytes);
}
#[wasm_bindgen_test]
fn test_seeded_extended_keygen_wasm() {
let seed_bytes: Vec<u8> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let seed = Uint8Array::from(&seed_bytes[..]);
let identity = ExtendedIdentity::generate_seeded(&seed);
let identity_trapdoor = *identity.get_trapdoor();
let identity_nullifier = *identity.get_nullifier();
let identity_secret = *identity.get_secret_hash();
let id_commitment = *identity.get_commitment();
let expected_identity_trapdoor_seed_bytes = str_to_fr(
"0x766ce6c7e7a01bdf5b3f257616f603918c30946fa23480f2859c597817e6716",
16,
)
.unwrap();
let expected_identity_nullifier_seed_bytes = str_to_fr(
"0x1f18714c7bc83b5bca9e89d404cf6f2f585bc4c0f7ed8b53742b7e2b298f50b4",
16,
)
.unwrap();
let expected_identity_secret_seed_bytes = str_to_fr(
"0x2aca62aaa7abaf3686fff2caf00f55ab9462dc12db5b5d4bcf3994e671f8e521",
16,
)
.unwrap();
let expected_id_commitment_seed_bytes = str_to_fr(
"0x68b66aa0a8320d2e56842581553285393188714c48f9b17acd198b4f1734c5c",
16,
)
.unwrap();
assert_eq!(identity_trapdoor, expected_identity_trapdoor_seed_bytes);
assert_eq!(identity_nullifier, expected_identity_nullifier_seed_bytes);
assert_eq!(identity_secret, expected_identity_secret_seed_bytes);
assert_eq!(id_commitment, expected_id_commitment_seed_bytes);
}
#[wasm_bindgen_test]
fn test_wasmfr() {
let wasmfr_zero = WasmFr::zero();
let fr_zero = Fr::from(0u8);
assert_eq!(*wasmfr_zero, fr_zero);
let wasmfr_one = WasmFr::one();
let fr_one = Fr::from(1u8);
assert_eq!(*wasmfr_one, fr_one);
let wasmfr_int = WasmFr::from_uint(42);
let fr_int = Fr::from(42u8);
assert_eq!(*wasmfr_int, fr_int);
let wasmfr_debug_str = wasmfr_int.debug();
assert_eq!(wasmfr_debug_str.to_string(), "42");
let identity = Identity::generate();
let mut id_secret_fr = *identity.get_secret_hash();
let id_secret_hash = IdSecret::from(&mut id_secret_fr);
let id_commitment = *identity.get_commitment();
let wasmfr_id_secret_hash = *identity.get_secret_hash();
assert_eq!(wasmfr_id_secret_hash, *id_secret_hash);
let wasmfr_id_commitment = *identity.get_commitment();
assert_eq!(wasmfr_id_commitment, id_commitment);
}
#[wasm_bindgen_test]
fn test_vec_wasmfr() {
let vec_fr = vec![Fr::from(1u8), Fr::from(2u8), Fr::from(3u8), Fr::from(4u8)];
let mut vec_wasmfr = VecWasmFr::new();
for fr in &vec_fr {
vec_wasmfr.push(&WasmFr::from(*fr));
}
let bytes_le = vec_wasmfr.to_bytes_le();
let expected_le = rln::utils::vec_fr_to_bytes_le(&vec_fr);
assert_eq!(bytes_le.to_vec(), expected_le);
let bytes_be = vec_wasmfr.to_bytes_be();
let expected_be = rln::utils::vec_fr_to_bytes_be(&vec_fr);
assert_eq!(bytes_be.to_vec(), expected_be);
let vec_wasmfr_from_le = match VecWasmFr::from_bytes_le(&bytes_le) {
Ok(v) => v,
Err(err) => panic!("VecWasmFr::from_bytes_le call failed: {}", err),
};
assert_eq!(vec_wasmfr_from_le.length(), vec_wasmfr.length());
for i in 0..vec_wasmfr.length() {
assert_eq!(
*vec_wasmfr_from_le.get(i).unwrap(),
*vec_wasmfr.get(i).unwrap()
);
}
let vec_wasmfr_from_be = match VecWasmFr::from_bytes_be(&bytes_be) {
Ok(v) => v,
Err(err) => panic!("VecWasmFr::from_bytes_be call failed: {}", err),
};
for i in 0..vec_wasmfr.length() {
assert_eq!(
*vec_wasmfr_from_be.get(i).unwrap(),
*vec_wasmfr.get(i).unwrap()
);
}
}
#[wasm_bindgen_test]
fn test_hash_to_field_wasm() {
let mut rng = thread_rng();
let signal_gen: [u8; 32] = rng.gen();
let signal = Uint8Array::from(&signal_gen[..]);
let wasmfr_le_1 = Hasher::hash_to_field_le(&signal);
let fr_le_2 = rln::hashers::hash_to_field_le(&signal_gen);
assert_eq!(*wasmfr_le_1, fr_le_2);
let wasmfr_be_1 = Hasher::hash_to_field_be(&signal);
let fr_be_2 = rln::hashers::hash_to_field_be(&signal_gen);
assert_eq!(*wasmfr_be_1, fr_be_2);
assert_eq!(*wasmfr_le_1, *wasmfr_be_1);
assert_eq!(fr_le_2, fr_be_2);
let hash_wasmfr_le_1 = wasmfr_le_1.to_bytes_le();
let hash_fr_le_2 = fr_to_bytes_le(&fr_le_2);
assert_eq!(hash_wasmfr_le_1.to_vec(), hash_fr_le_2);
let hash_wasmfr_be_1 = wasmfr_be_1.to_bytes_be();
let hash_fr_be_2 = fr_to_bytes_be(&fr_be_2);
assert_eq!(hash_wasmfr_be_1.to_vec(), hash_fr_be_2);
assert_ne!(hash_wasmfr_le_1.to_vec(), hash_wasmfr_be_1.to_vec());
assert_ne!(hash_fr_le_2, hash_fr_be_2);
}
#[wasm_bindgen_test]
fn test_poseidon_hash_pair_wasm() {
let input_1 = Fr::from(42u8);
let input_2 = Fr::from(99u8);
let expected_hash = poseidon_hash(&[input_1, input_2]);
let wasmfr_1 = WasmFr::from_uint(42);
let wasmfr_2 = WasmFr::from_uint(99);
let received_hash = Hasher::poseidon_hash_pair(&wasmfr_1, &wasmfr_2);
assert_eq!(*received_hash, expected_hash);
}
}