mirror of
https://github.com/vacp2p/zerokit.git
synced 2026-01-09 21:58:06 -05:00
Changes: - Unified error types (`PoseidonError`, `HashError`, etc.) across hashing, keygen, witness calculation, and serialization for consistent and descriptive error handling. - Refactored tests and examples to use `unwrap()` where safe, and limited `expect()` in library code to non-panicking cases with clear messaging. - Improved witness and proof generation by removing panicking code paths and enforcing proper error propagation. - Cleaned up outdated imports, removed unused operations in `graph.rs`, and updated public API documentation. - Updated C, Nim, and WASM FFI bindings with more robust serialization and clearer error log messages. - Added keywords to package.json and update dependencies in Makefile.toml and Nightly CI.
289 lines
10 KiB
Rust
289 lines
10 KiB
Rust
#[cfg(test)]
|
|
mod test {
|
|
use rand::Rng;
|
|
use rln::{ffi::ffi_utils::*, prelude::*};
|
|
|
|
#[test]
|
|
// Tests hash to field using FFI APIs
|
|
fn test_seeded_keygen_ffi() {
|
|
// We generate a new identity pair from an input seed
|
|
let seed_bytes: Vec<u8> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
let res = match ffi_seeded_key_gen(&seed_bytes.into()) {
|
|
CResult {
|
|
ok: Some(vec_cfr),
|
|
err: None,
|
|
} => vec_cfr,
|
|
CResult {
|
|
ok: None,
|
|
err: Some(err),
|
|
} => panic!("ffi_seeded_key_gen call failed: {}", err),
|
|
_ => unreachable!(),
|
|
};
|
|
let identity_secret = res.first().unwrap();
|
|
let id_commitment = res.get(1).unwrap();
|
|
|
|
// We check against expected values
|
|
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);
|
|
}
|
|
|
|
#[test]
|
|
// Tests hash to field using FFI APIs
|
|
fn test_seeded_extended_keygen_ffi() {
|
|
// We generate a new identity tuple from an input seed
|
|
let seed_bytes: Vec<u8> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
let key_gen = match ffi_seeded_extended_key_gen(&seed_bytes.into()) {
|
|
CResult {
|
|
ok: Some(vec_cfr),
|
|
err: None,
|
|
} => vec_cfr,
|
|
CResult {
|
|
ok: None,
|
|
err: Some(err),
|
|
} => panic!("ffi_seeded_extended_key_gen call failed: {}", err),
|
|
_ => unreachable!(),
|
|
};
|
|
let identity_trapdoor = *key_gen[0];
|
|
let identity_nullifier = *key_gen[1];
|
|
let identity_secret = *key_gen[2];
|
|
let id_commitment = *key_gen[3];
|
|
|
|
// We check against expected values
|
|
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);
|
|
}
|
|
|
|
#[test]
|
|
// Test CFr FFI functions
|
|
fn test_cfr_ffi() {
|
|
let cfr_zero = ffi_cfr_zero();
|
|
let fr_zero = rln::circuit::Fr::from(0u8);
|
|
assert_eq!(*cfr_zero, fr_zero);
|
|
|
|
let cfr_one = ffi_cfr_one();
|
|
let fr_one = rln::circuit::Fr::from(1u8);
|
|
assert_eq!(*cfr_one, fr_one);
|
|
|
|
let cfr_int = ffi_uint_to_cfr(42);
|
|
let fr_int = rln::circuit::Fr::from(42u8);
|
|
assert_eq!(*cfr_int, fr_int);
|
|
|
|
let cfr_debug_str = ffi_cfr_debug(Some(&cfr_int));
|
|
assert_eq!(cfr_debug_str.to_string(), "42");
|
|
|
|
let key_gen = match ffi_key_gen() {
|
|
CResult {
|
|
ok: Some(vec_cfr),
|
|
err: None,
|
|
} => vec_cfr,
|
|
CResult {
|
|
ok: None,
|
|
err: Some(err),
|
|
} => panic!("ffi_key_gen call failed: {}", err),
|
|
_ => unreachable!(),
|
|
};
|
|
let mut id_secret_fr = *key_gen[0];
|
|
let id_secret_hash = IdSecret::from(&mut id_secret_fr);
|
|
let id_commitment = *key_gen[1];
|
|
let cfr_id_secret_hash = ffi_vec_cfr_get(&key_gen, 0).unwrap();
|
|
assert_eq!(*cfr_id_secret_hash, *id_secret_hash);
|
|
let cfr_id_commitment = ffi_vec_cfr_get(&key_gen, 1).unwrap();
|
|
assert_eq!(*cfr_id_commitment, id_commitment);
|
|
}
|
|
|
|
#[test]
|
|
// Test Vec<u8> FFI functions
|
|
fn test_vec_u8_ffi() {
|
|
let mut rng = rand::thread_rng();
|
|
let signal_gen: [u8; 32] = rng.gen();
|
|
let signal: Vec<u8> = signal_gen.to_vec();
|
|
|
|
let bytes_le = ffi_vec_u8_to_bytes_le(&signal.clone().into());
|
|
let expected_le = vec_u8_to_bytes_le(&signal);
|
|
assert_eq!(bytes_le.iter().copied().collect::<Vec<_>>(), expected_le);
|
|
|
|
let bytes_be = ffi_vec_u8_to_bytes_be(&signal.clone().into());
|
|
let expected_be = vec_u8_to_bytes_be(&signal);
|
|
assert_eq!(bytes_be.iter().copied().collect::<Vec<_>>(), expected_be);
|
|
|
|
let signal_from_le = match ffi_bytes_le_to_vec_u8(&bytes_le) {
|
|
CResult {
|
|
ok: Some(vec_u8),
|
|
err: None,
|
|
} => vec_u8,
|
|
CResult {
|
|
ok: None,
|
|
err: Some(err),
|
|
} => panic!("ffi_bytes_le_to_vec_u8 call failed: {}", err),
|
|
_ => unreachable!(),
|
|
};
|
|
assert_eq!(signal_from_le.iter().copied().collect::<Vec<_>>(), signal);
|
|
|
|
let signal_from_be = match ffi_bytes_be_to_vec_u8(&bytes_be) {
|
|
CResult {
|
|
ok: Some(vec_u8),
|
|
err: None,
|
|
} => vec_u8,
|
|
CResult {
|
|
ok: None,
|
|
err: Some(err),
|
|
} => panic!("ffi_bytes_be_to_vec_u8 call failed: {}", err),
|
|
_ => unreachable!(),
|
|
};
|
|
assert_eq!(signal_from_be.iter().copied().collect::<Vec<_>>(), signal);
|
|
}
|
|
|
|
#[test]
|
|
// Test Vec<CFr> FFI functions
|
|
fn test_vec_cfr_ffi() {
|
|
let vec_fr = [Fr::from(1u8), Fr::from(2u8), Fr::from(3u8), Fr::from(4u8)];
|
|
let vec_cfr: Vec<CFr> = vec_fr.iter().map(|fr| CFr::from(*fr)).collect();
|
|
|
|
let bytes_le = ffi_vec_cfr_to_bytes_le(&vec_cfr.clone().into());
|
|
let expected_le = vec_fr_to_bytes_le(&vec_fr);
|
|
assert_eq!(bytes_le.iter().copied().collect::<Vec<_>>(), expected_le);
|
|
|
|
let bytes_be = ffi_vec_cfr_to_bytes_be(&vec_cfr.clone().into());
|
|
let expected_be = vec_fr_to_bytes_be(&vec_fr);
|
|
assert_eq!(bytes_be.iter().copied().collect::<Vec<_>>(), expected_be);
|
|
|
|
let vec_cfr_from_le = match ffi_bytes_le_to_vec_cfr(&bytes_le) {
|
|
CResult {
|
|
ok: Some(vec_cfr),
|
|
err: None,
|
|
} => vec_cfr,
|
|
CResult {
|
|
ok: None,
|
|
err: Some(err),
|
|
} => panic!("ffi_bytes_le_to_vec_cfr call failed: {}", err),
|
|
_ => unreachable!(),
|
|
};
|
|
assert_eq!(vec_cfr_from_le.iter().copied().collect::<Vec<_>>(), vec_cfr);
|
|
|
|
let vec_cfr_from_be = match ffi_bytes_be_to_vec_cfr(&bytes_be) {
|
|
CResult {
|
|
ok: Some(vec_cfr),
|
|
err: None,
|
|
} => vec_cfr,
|
|
CResult {
|
|
ok: None,
|
|
err: Some(err),
|
|
} => panic!("ffi_bytes_be_to_vec_cfr call failed: {}", err),
|
|
_ => unreachable!(),
|
|
};
|
|
assert_eq!(vec_cfr_from_be.iter().copied().collect::<Vec<_>>(), vec_cfr);
|
|
}
|
|
|
|
#[test]
|
|
// Tests hash to field using FFI APIs
|
|
fn test_hash_to_field_ffi() {
|
|
let mut rng = rand::thread_rng();
|
|
let signal_gen: [u8; 32] = rng.gen();
|
|
let signal: Vec<u8> = signal_gen.to_vec();
|
|
|
|
let cfr_le_1 = match ffi_hash_to_field_le(&signal.clone().into()) {
|
|
CResult {
|
|
ok: Some(cfr),
|
|
err: None,
|
|
} => cfr,
|
|
CResult {
|
|
ok: None,
|
|
err: Some(err),
|
|
} => panic!("ffi_hash_to_field_le call failed: {}", err),
|
|
_ => unreachable!(),
|
|
};
|
|
let fr_le_2 = hash_to_field_le(&signal).unwrap();
|
|
assert_eq!(*cfr_le_1, fr_le_2);
|
|
|
|
let cfr_be_1 = match ffi_hash_to_field_be(&signal.clone().into()) {
|
|
CResult {
|
|
ok: Some(cfr),
|
|
err: None,
|
|
} => cfr,
|
|
CResult {
|
|
ok: None,
|
|
err: Some(err),
|
|
} => panic!("ffi_hash_to_field_be call failed: {}", err),
|
|
_ => unreachable!(),
|
|
};
|
|
let fr_be_2 = hash_to_field_be(&signal).unwrap();
|
|
assert_eq!(*cfr_le_1, fr_be_2);
|
|
|
|
assert_eq!(*cfr_le_1, *cfr_be_1);
|
|
assert_eq!(fr_le_2, fr_be_2);
|
|
|
|
let hash_cfr_le_1 = ffi_cfr_to_bytes_le(&cfr_le_1)
|
|
.iter()
|
|
.copied()
|
|
.collect::<Vec<_>>();
|
|
let hash_fr_le_2 = fr_to_bytes_le(&fr_le_2);
|
|
assert_eq!(hash_cfr_le_1, hash_fr_le_2);
|
|
|
|
let hash_cfr_be_1 = ffi_cfr_to_bytes_be(&cfr_be_1)
|
|
.iter()
|
|
.copied()
|
|
.collect::<Vec<_>>();
|
|
let hash_fr_be_2 = fr_to_bytes_be(&fr_be_2);
|
|
assert_eq!(hash_cfr_be_1, hash_fr_be_2);
|
|
|
|
assert_ne!(hash_cfr_le_1, hash_cfr_be_1);
|
|
assert_ne!(hash_fr_le_2, hash_fr_be_2);
|
|
}
|
|
|
|
#[test]
|
|
// Test Poseidon hash FFI
|
|
fn test_poseidon_hash_pair_ffi() {
|
|
let input_1 = Fr::from(42u8);
|
|
let input_2 = Fr::from(99u8);
|
|
|
|
let expected_hash = poseidon_hash(&[input_1, input_2]).unwrap();
|
|
let received_hash_cfr =
|
|
match ffi_poseidon_hash_pair(&CFr::from(input_1), &CFr::from(input_2)) {
|
|
CResult {
|
|
ok: Some(cfr),
|
|
err: None,
|
|
} => cfr,
|
|
CResult {
|
|
ok: None,
|
|
err: Some(err),
|
|
} => panic!("ffi_poseidon_hash_pair call failed: {}", err),
|
|
_ => unreachable!(),
|
|
};
|
|
assert_eq!(*received_hash_cfr, expected_hash);
|
|
}
|
|
}
|