diff --git a/Cargo.lock b/Cargo.lock index 3fe71765..8fffc3f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2230,6 +2230,7 @@ dependencies = [ "serde_json", "thiserror", "tiny-keccak", + "zeroize", ] [[package]] diff --git a/rln-cli/Cargo.lock b/rln-cli/Cargo.lock index fcdd8541..d1837b13 100644 --- a/rln-cli/Cargo.lock +++ b/rln-cli/Cargo.lock @@ -1953,6 +1953,7 @@ dependencies = [ "rayon", "serde_json", "thiserror", + "zeroize", ] [[package]] diff --git a/rln-cli/src/examples/multi_message_id.rs b/rln-cli/src/examples/multi_message_id.rs index fab0db84..e6de8955 100644 --- a/rln-cli/src/examples/multi_message_id.rs +++ b/rln-cli/src/examples/multi_message_id.rs @@ -6,8 +6,8 @@ use std::{ use clap::{Parser, Subcommand}; use rln::prelude::{ default_graph_multi, default_zkey_multi, hash_to_field_le, keygen, poseidon_hash, - ArkGroth16Backend, Fr, IdSecret, PmTree, PmTreeSledConfig, PoseidonHash, RLNBuilder, - RLNProofValues, RLNWitnessInput, RecoverSecret, SledDB, Stateful, RLN, + ArkGroth16Backend, Fr, PmTree, PmTreeSledConfig, PoseidonHash, RLNBuilder, RLNProofValues, + RLNWitnessInput, RecoverSecret, SecretFr, SledDB, Stateful, RLN, }; use zerokit_utils::merkle_tree::{Hasher, ZerokitMerkleProof, ZerokitMerkleTree}; @@ -46,7 +46,7 @@ enum Commands { #[derive(Debug, Clone)] struct Identity { - identity_secret: IdSecret, + identity_secret: SecretFr, id_commitment: Fr, } diff --git a/rln-cli/src/examples/partial.rs b/rln-cli/src/examples/partial.rs index 71018f69..727148a3 100644 --- a/rln-cli/src/examples/partial.rs +++ b/rln-cli/src/examples/partial.rs @@ -6,8 +6,8 @@ use std::{ use clap::{Parser, Subcommand}; use rln::prelude::{ default_graph_single, default_zkey_single, hash_to_field_le, keygen, poseidon_hash, - ArkGroth16Backend, Fr, IdSecret, PartialProof, PoseidonHash, RLNBuilder, - RLNPartialWitnessInput, RLNProofValues, RLNWitnessInput, RecoverSecret, Stateful, RLN, + ArkGroth16Backend, Fr, PartialProof, PoseidonHash, RLNBuilder, RLNPartialWitnessInput, + RLNProofValues, RLNWitnessInput, RecoverSecret, SecretFr, Stateful, RLN, }; use zerokit_utils::merkle_tree::{FullMerkleTree, Hasher, ZerokitMerkleProof, ZerokitMerkleTree}; @@ -48,7 +48,7 @@ enum Commands { #[derive(Debug, Clone)] struct Identity { - identity_secret: IdSecret, + identity_secret: SecretFr, id_commitment: Fr, } diff --git a/rln-cli/src/examples/relay.rs b/rln-cli/src/examples/relay.rs index 647314b6..baa36661 100644 --- a/rln-cli/src/examples/relay.rs +++ b/rln-cli/src/examples/relay.rs @@ -8,8 +8,8 @@ use std::{ use clap::{Parser, Subcommand}; use rln::prelude::{ graph_from_raw, hash_to_field_le, keygen, poseidon_hash, zkey_from_raw, ArkGroth16Backend, Fr, - IdSecret, PmTree, PmTreeMode, PmTreeSledConfig, PoseidonHash, RLNBuilder, RLNProofValues, - RLNWitnessInput, RecoverSecret, SledDB, Stateful, RLN, + PmTree, PmTreeMode, PmTreeSledConfig, PoseidonHash, RLNBuilder, RLNProofValues, + RLNWitnessInput, RecoverSecret, SecretFr, SledDB, Stateful, RLN, }; use zerokit_utils::merkle_tree::{Hasher, ZerokitMerkleProof, ZerokitMerkleTree}; @@ -44,7 +44,7 @@ enum Commands { #[derive(Debug, Clone)] struct Identity { - identity_secret: IdSecret, + identity_secret: SecretFr, id_commitment: Fr, } diff --git a/rln-cli/src/examples/stateless.rs b/rln-cli/src/examples/stateless.rs index 35c32f7f..ed541e77 100644 --- a/rln-cli/src/examples/stateless.rs +++ b/rln-cli/src/examples/stateless.rs @@ -6,8 +6,8 @@ use std::{ use clap::{Parser, Subcommand}; use rln::prelude::{ default_graph_single, default_zkey_single, hash_to_field_le, keygen, poseidon_hash, - ArkGroth16Backend, Fr, IdSecret, PoseidonHash, RLNBuilder, RLNProofValues, RLNWitnessInput, - RecoverSecret, Stateless, DEFAULT_TREE_DEPTH, RLN, + ArkGroth16Backend, Fr, PoseidonHash, RLNBuilder, RLNProofValues, RLNWitnessInput, + RecoverSecret, SecretFr, Stateless, DEFAULT_TREE_DEPTH, RLN, }; use zerokit_utils::merkle_tree::{ Hasher, OptimalMerkleTree, ZerokitMerkleProof, ZerokitMerkleTree, @@ -43,7 +43,7 @@ enum Commands { #[derive(Debug, Clone)] struct Identity { - identity_secret: IdSecret, + identity_secret: SecretFr, id_commitment: Fr, } diff --git a/rln-wasm/Cargo.lock b/rln-wasm/Cargo.lock index 13d8eb18..57057e07 100644 --- a/rln-wasm/Cargo.lock +++ b/rln-wasm/Cargo.lock @@ -1269,6 +1269,7 @@ dependencies = [ "wasm-bindgen-rayon", "wasm-bindgen-test", "web-sys", + "zeroize", "zerokit_utils", ] @@ -2126,6 +2127,7 @@ dependencies = [ "rayon", "serde_json", "thiserror", + "zeroize", ] [[package]] diff --git a/rln-wasm/Cargo.toml b/rln-wasm/Cargo.toml index 69b195b0..fc64fb75 100644 --- a/rln-wasm/Cargo.toml +++ b/rln-wasm/Cargo.toml @@ -18,6 +18,7 @@ wasm-bindgen-rayon = { version = "1.3.0", features = [ ark-relations = { version = "0.5.1", features = ["std"] } ark-groth16 = { version = "0.5.0", default-features = false } rand = "0.8.6" +zeroize = "1.8.2" # The `console_error_panic_hook` crate provides better debugging of panics by # logging them with `console.error`. This is great for development, but requires diff --git a/rln-wasm/examples/common.js b/rln-wasm/examples/common.js index 99892145..32a106d9 100644 --- a/rln-wasm/examples/common.js +++ b/rln-wasm/examples/common.js @@ -47,8 +47,8 @@ export async function initRLN(enableMultiMessageId = false) { export function createMember(rlnWasm) { console.log("\nGenerating identity keys"); - const identity = rlnWasm.Identity.generate(); - const identitySecret = identity.getSecretHash(); + const identity = rlnWasm.WasmIdentityKeys.generate(); + const identitySecret = identity.getSecret(); const idCommitment = identity.getCommitment(); console.log(" - identity generated successfully"); console.log(" - identity secret = " + identitySecret.debug()); @@ -59,7 +59,7 @@ export function createMember(rlnWasm) { console.log(" - user message limit = " + userMessageLimit.debug()); console.log("\nComputing rate commitment"); - const rateCommitment = rlnWasm.Hasher.poseidonHashPair( + const rateCommitment = rlnWasm.WasmHasher.poseidonHashPair( idCommitment, userMessageLimit, ); @@ -79,9 +79,9 @@ export function computeMerkleProof(rlnWasm, rateCommitment) { const defaultLeaf = rlnWasm.WasmFr.zero(); const defaultHashes = []; - defaultHashes[0] = rlnWasm.Hasher.poseidonHashPair(defaultLeaf, defaultLeaf); + defaultHashes[0] = rlnWasm.WasmHasher.poseidonHashPair(defaultLeaf, defaultLeaf); for (let i = 1; i < TREE_DEPTH - 1; i++) { - defaultHashes[i] = rlnWasm.Hasher.poseidonHashPair( + defaultHashes[i] = rlnWasm.WasmHasher.poseidonHashPair( defaultHashes[i - 1], defaultHashes[i - 1], ); @@ -96,12 +96,12 @@ export function computeMerkleProof(rlnWasm, rateCommitment) { console.log("\nComputing Merkle root for stateless mode"); console.log(" - computing root for index 0 with rate commitment"); - let computedRoot = rlnWasm.Hasher.poseidonHashPair( + let computedRoot = rlnWasm.WasmHasher.poseidonHashPair( rateCommitment, defaultLeaf, ); for (let i = 1; i < TREE_DEPTH; i++) { - computedRoot = rlnWasm.Hasher.poseidonHashPair( + computedRoot = rlnWasm.WasmHasher.poseidonHashPair( computedRoot, defaultHashes[i - 1], ); @@ -115,7 +115,7 @@ export function computeMerkleProof(rlnWasm, rateCommitment) { } export function hashSignal(rlnWasm, signal) { - return rlnWasm.Hasher.hashToFieldLE(signal); + return rlnWasm.WasmHasher.hashToFieldLE(signal); } export function computeExternalNullifier( @@ -124,19 +124,19 @@ export function computeExternalNullifier( rlnIdStr = "test-rln-identifier", ) { console.log("\nHashing epoch"); - const epoch = rlnWasm.Hasher.hashToFieldLE( + const epoch = rlnWasm.WasmHasher.hashToFieldLE( new TextEncoder().encode(epochStr), ); console.log(" - epoch = " + epoch.debug()); console.log("\nHashing RLN identifier"); - const rlnIdentifier = rlnWasm.Hasher.hashToFieldLE( + const rlnIdentifier = rlnWasm.WasmHasher.hashToFieldLE( new TextEncoder().encode(rlnIdStr), ); console.log(" - RLN identifier = " + rlnIdentifier.debug()); console.log("\nComputing Poseidon hash for external nullifier"); - const externalNullifier = rlnWasm.Hasher.poseidonHashPair( + const externalNullifier = rlnWasm.WasmHasher.poseidonHashPair( epoch, rlnIdentifier, ); diff --git a/rln-wasm/src/lib.rs b/rln-wasm/src/lib.rs index 5bd86e34..2d01e4b3 100644 --- a/rln-wasm/src/lib.rs +++ b/rln-wasm/src/lib.rs @@ -10,7 +10,9 @@ pub use wasm_rln::{ WasmRLN, WasmRLNPartialProof, WasmRLNPartialWitnessInput, WasmRLNProof, WasmRLNProofValues, WasmRLNWitnessInput, }; -pub use wasm_utils::{ExtendedIdentity, Hasher, Identity, VecWasmFr, WasmFr}; +pub use wasm_utils::{ + VecWasmFr, WasmExtendedIdentityKeys, WasmFr, WasmHasher, WasmIdentityKeys, WasmSecretFr, +}; #[cfg(feature = "panic_hook")] #[wasm_bindgen(js_name = initPanicHook)] diff --git a/rln-wasm/src/wasm_rln.rs b/rln-wasm/src/wasm_rln.rs index 89e7595d..d300b92b 100644 --- a/rln-wasm/src/wasm_rln.rs +++ b/rln-wasm/src/wasm_rln.rs @@ -5,7 +5,7 @@ use js_sys::Uint8Array; use rln::prelude::*; use wasm_bindgen::prelude::*; -use crate::wasm_utils::{VecWasmFr, WasmFr}; +use crate::wasm_utils::{VecWasmFr, WasmFr, WasmSecretFr}; // WasmRLN @@ -100,7 +100,7 @@ pub struct WasmRLNWitnessInput(RLNWitnessInput); impl WasmRLNWitnessInput { #[wasm_bindgen(js_name = newSingle)] pub fn new_single( - identity_secret: &WasmFr, + identity_secret: &WasmSecretFr, user_message_limit: &WasmFr, message_id: &WasmFr, path_elements: &VecWasmFr, @@ -108,12 +108,11 @@ impl WasmRLNWitnessInput { x: &WasmFr, external_nullifier: &WasmFr, ) -> Result { - let mut identity_secret_fr = identity_secret.inner(); let path_elements: Vec = path_elements.inner(); let identity_path_index: Vec = identity_path_index.to_vec(); let witness = RLNWitnessInput::new_single() - .identity_secret(IdSecret::from(&mut identity_secret_fr)) + .identity_secret(identity_secret.inner().clone()) .user_message_limit(user_message_limit.inner()) .path_elements(path_elements) .identity_path_index(identity_path_index) @@ -129,7 +128,7 @@ impl WasmRLNWitnessInput { #[allow(clippy::too_many_arguments)] #[wasm_bindgen(js_name = newMulti)] pub fn new_multi( - identity_secret: &WasmFr, + identity_secret: &WasmSecretFr, user_message_limit: &WasmFr, message_ids: VecWasmFr, path_elements: &VecWasmFr, @@ -138,7 +137,6 @@ impl WasmRLNWitnessInput { external_nullifier: &WasmFr, selector_used: Uint8Array, ) -> Result { - let mut identity_secret_fr = identity_secret.inner(); let path_elements: Vec = path_elements.inner(); let identity_path_index: Vec = identity_path_index.to_vec(); @@ -146,7 +144,7 @@ impl WasmRLNWitnessInput { let selector_used: Vec = selector_used.to_vec().iter().map(|&b| b != 0).collect(); let witness = RLNWitnessInput::new_multi() - .identity_secret(IdSecret::from(&mut identity_secret_fr)) + .identity_secret(identity_secret.inner().clone()) .user_message_limit(user_message_limit.inner()) .path_elements(path_elements) .identity_path_index(identity_path_index) @@ -161,8 +159,8 @@ impl WasmRLNWitnessInput { } #[wasm_bindgen(js_name = getIdentitySecret)] - pub fn get_identity_secret(&self) -> WasmFr { - WasmFr::from(**self.0.identity_secret()) + pub fn get_identity_secret(&self) -> WasmSecretFr { + WasmSecretFr::from(self.0.identity_secret().clone()) } #[wasm_bindgen(js_name = getUserMessageLimit)] @@ -256,17 +254,16 @@ pub struct WasmRLNPartialWitnessInput(RLNPartialWitnessInput); impl WasmRLNPartialWitnessInput { #[wasm_bindgen(js_name = new)] pub fn new( - identity_secret: &WasmFr, + identity_secret: &WasmSecretFr, user_message_limit: &WasmFr, path_elements: &VecWasmFr, identity_path_index: &Uint8Array, ) -> Result { - let mut identity_secret_fr = identity_secret.inner(); let path_elements: Vec = path_elements.inner(); let identity_path_index: Vec = identity_path_index.to_vec(); let witness = RLNPartialWitnessInput::new() - .identity_secret(IdSecret::from(&mut identity_secret_fr)) + .identity_secret(identity_secret.inner().clone()) .user_message_limit(user_message_limit.inner()) .path_elements(path_elements) .identity_path_index(identity_path_index) @@ -472,22 +469,22 @@ impl WasmRLNProofValues { share1_y: &WasmFr, share2_x: &WasmFr, share2_y: &WasmFr, - ) -> Result { + ) -> Result { let share1 = (share1_x.inner(), share1_y.inner()); let share2 = (share2_x.inner(), share2_y.inner()); let secret = compute_id_secret(share1, share2).map_err(|err| err.to_string())?; - Ok(WasmFr::from(*secret)) + Ok(WasmSecretFr::from(secret)) } #[wasm_bindgen(js_name = recoverIdSecret)] pub fn recover_id_secret( proof_values_1: &WasmRLNProofValues, proof_values_2: &WasmRLNProofValues, - ) -> Result { + ) -> Result { let recovered_identity_secret = proof_values_1 .0 .recover_secret(&proof_values_2.0) .map_err(|err| err.to_string())?; - Ok(WasmFr::from(*recovered_identity_secret)) + Ok(WasmSecretFr::from(recovered_identity_secret)) } } diff --git a/rln-wasm/src/wasm_utils.rs b/rln-wasm/src/wasm_utils.rs index 01fb4876..e067d12a 100644 --- a/rln-wasm/src/wasm_utils.rs +++ b/rln-wasm/src/wasm_utils.rs @@ -5,6 +5,7 @@ use std::ops::Deref; use js_sys::Uint8Array; use rln::prelude::*; use wasm_bindgen::prelude::*; +use zeroize::Zeroizing; // WasmFr @@ -85,6 +86,31 @@ impl WasmFr { } } +// WasmSecretFr (opaque secret field element, zeroized on drop) + +#[wasm_bindgen] +pub struct WasmSecretFr(SecretFr); + +#[wasm_bindgen] +impl WasmSecretFr { + #[wasm_bindgen(js_name = debug)] + pub fn debug(&self) -> String { + format!("{:?}", self.0) + } +} + +impl WasmSecretFr { + pub fn inner(&self) -> &SecretFr { + &self.0 + } +} + +impl From for WasmSecretFr { + fn from(secret: SecretFr) -> Self { + Self(secret) + } +} + // VecWasmFr #[wasm_bindgen] @@ -132,7 +158,7 @@ impl VecWasmFr { #[wasm_bindgen(js_name = get)] pub fn get(&self, index: usize) -> Option { - self.0.get(index).map(|&fr| WasmFr(fr)) + self.0.get(index).map(|&fr| WasmFr::from(fr)) } #[wasm_bindgen(js_name = length)] @@ -166,10 +192,10 @@ impl From> for VecWasmFr { // Uint8Array #[wasm_bindgen] -pub struct Uint8ArrayUtils; +pub struct WasmUint8ArrayUtils; #[wasm_bindgen] -impl Uint8ArrayUtils { +impl WasmUint8ArrayUtils { #[wasm_bindgen(js_name = toBytesLE)] pub fn to_bytes_le(input: &Uint8Array) -> Result { let input_vec = input.to_vec(); @@ -205,78 +231,71 @@ impl Uint8ArrayUtils { } } -// Hasher +// WasmHasher #[wasm_bindgen] -pub struct Hasher; +pub struct WasmHasher; #[wasm_bindgen] -impl Hasher { +impl WasmHasher { #[wasm_bindgen(js_name = hashToFieldLE)] pub fn hash_to_field_le(input: &Uint8Array) -> WasmFr { - WasmFr(hash_to_field_le(&input.to_vec())) + WasmFr::from(hash_to_field_le(&input.to_vec())) } #[wasm_bindgen(js_name = hashToFieldBE)] pub fn hash_to_field_be(input: &Uint8Array) -> WasmFr { - WasmFr(hash_to_field_be(&input.to_vec())) + WasmFr::from(hash_to_field_be(&input.to_vec())) } #[wasm_bindgen(js_name = poseidonHashPair)] pub fn poseidon_hash_pair(a: &WasmFr, b: &WasmFr) -> WasmFr { - WasmFr(poseidon_hash_pair(a.0, b.0)) + WasmFr::from(poseidon_hash_pair(a.0, b.0)) } } -// Identity +// WasmIdentityKeys #[wasm_bindgen] -pub struct Identity { - identity_secret: Fr, +pub struct WasmIdentityKeys { + identity_secret: SecretFr, id_commitment: Fr, } #[wasm_bindgen] -impl Identity { +impl WasmIdentityKeys { #[wasm_bindgen(js_name = generate)] - pub fn generate() -> Identity { + pub fn generate() -> WasmIdentityKeys { let (identity_secret, id_commitment) = keygen(); - Identity { - // TODO(PR12): Leaking secret here, consider using a more secure approach to handle secrets in WASM. - identity_secret: *identity_secret, + WasmIdentityKeys { + identity_secret, id_commitment, } } #[wasm_bindgen(js_name = generateSeeded)] - pub fn generate_seeded(seed: &Uint8Array) -> Identity { + pub fn generate_seeded(seed: &Uint8Array) -> WasmIdentityKeys { let seed_vec = seed.to_vec(); let (identity_secret, id_commitment) = seeded_keygen(&seed_vec); - Identity { - // TODO(PR12): Leaking secret here, consider using a more secure approach to handle secrets in WASM. - identity_secret: *identity_secret, + WasmIdentityKeys { + identity_secret, id_commitment, } } - #[wasm_bindgen(js_name = getSecretHash)] - pub fn get_secret_hash(&self) -> WasmFr { - WasmFr(self.identity_secret) + #[wasm_bindgen(js_name = getSecret)] + pub fn get_secret(&self) -> WasmSecretFr { + WasmSecretFr::from(self.identity_secret.clone()) } #[wasm_bindgen(js_name = getCommitment)] pub fn get_commitment(&self) -> WasmFr { - WasmFr(self.id_commitment) - } - - #[wasm_bindgen(js_name = toArray)] - pub fn to_array(&self) -> VecWasmFr { - VecWasmFr(vec![self.identity_secret, self.id_commitment]) + WasmFr::from(self.id_commitment) } #[wasm_bindgen(js_name = toBytesLE)] pub fn to_bytes_le(&self) -> Result { - let vec_fr = vec![self.identity_secret, self.id_commitment]; + let vec_fr = Zeroizing::new(vec![*self.identity_secret, self.id_commitment]); let mut bytes = Vec::new(); vec_fr .serialize_compressed(&mut bytes) @@ -286,58 +305,61 @@ impl Identity { #[wasm_bindgen(js_name = toBytesBE)] pub fn to_bytes_be(&self) -> Result { - let vec_fr = vec![self.identity_secret, self.id_commitment]; + let vec_fr = Zeroizing::new(vec![*self.identity_secret, self.id_commitment]); let mut bytes = Vec::new(); - CanonicalSerializeBE::serialize(&vec_fr, &mut bytes).map_err(|err| err.to_string())?; + CanonicalSerializeBE::serialize(&*vec_fr, &mut bytes).map_err(|err| err.to_string())?; Ok(Uint8Array::from(&bytes[..])) } #[wasm_bindgen(js_name = fromBytesLE)] - pub fn from_bytes_le(bytes: &Uint8Array) -> Result { + pub fn from_bytes_le(bytes: &Uint8Array) -> Result { let bytes_vec = bytes.to_vec(); - let vec_fr = - Vec::::deserialize_compressed(&bytes_vec[..]).map_err(|err| err.to_string())?; + let mut vec_fr = Zeroizing::new( + Vec::::deserialize_compressed(&bytes_vec[..]).map_err(|err| err.to_string())?, + ); if vec_fr.len() != 2 { return Err(format!("Expected 2 elements, got {}", vec_fr.len())); } - Ok(Identity { - identity_secret: vec_fr[0], + Ok(WasmIdentityKeys { + identity_secret: SecretFr::from(&mut vec_fr[0]), id_commitment: vec_fr[1], }) } #[wasm_bindgen(js_name = fromBytesBE)] - pub fn from_bytes_be(bytes: &Uint8Array) -> Result { + pub fn from_bytes_be(bytes: &Uint8Array) -> Result { let bytes_vec = bytes.to_vec(); - let vec_fr = as CanonicalDeserializeBE>::deserialize(&bytes_vec[..]) - .map_err(|err| err.to_string())?; + let mut vec_fr = Zeroizing::new( + as CanonicalDeserializeBE>::deserialize(&bytes_vec[..]) + .map_err(|err| err.to_string())?, + ); if vec_fr.len() != 2 { return Err(format!("Expected 2 elements, got {}", vec_fr.len())); } - Ok(Identity { - identity_secret: vec_fr[0], + Ok(WasmIdentityKeys { + identity_secret: SecretFr::from(&mut vec_fr[0]), id_commitment: vec_fr[1], }) } } -// ExtendedIdentity +// WasmExtendedIdentityKeys #[wasm_bindgen] -pub struct ExtendedIdentity { - identity_trapdoor: Fr, - identity_nullifier: Fr, - identity_secret: Fr, +pub struct WasmExtendedIdentityKeys { + identity_trapdoor: SecretFr, + identity_nullifier: SecretFr, + identity_secret: SecretFr, id_commitment: Fr, } #[wasm_bindgen] -impl ExtendedIdentity { +impl WasmExtendedIdentityKeys { #[wasm_bindgen(js_name = generate)] - pub fn generate() -> ExtendedIdentity { + pub fn generate() -> WasmExtendedIdentityKeys { let (identity_trapdoor, identity_nullifier, identity_secret, id_commitment) = extended_keygen(); - ExtendedIdentity { + WasmExtendedIdentityKeys { identity_trapdoor, identity_nullifier, identity_secret, @@ -346,11 +368,11 @@ impl ExtendedIdentity { } #[wasm_bindgen(js_name = generateSeeded)] - pub fn generate_seeded(seed: &Uint8Array) -> ExtendedIdentity { + pub fn generate_seeded(seed: &Uint8Array) -> WasmExtendedIdentityKeys { let seed_vec = seed.to_vec(); let (identity_trapdoor, identity_nullifier, identity_secret, id_commitment) = extended_seeded_keygen(&seed_vec); - ExtendedIdentity { + WasmExtendedIdentityKeys { identity_trapdoor, identity_nullifier, identity_secret, @@ -359,43 +381,33 @@ impl ExtendedIdentity { } #[wasm_bindgen(js_name = getTrapdoor)] - pub fn get_trapdoor(&self) -> WasmFr { - WasmFr(self.identity_trapdoor) + pub fn get_trapdoor(&self) -> WasmSecretFr { + WasmSecretFr::from(self.identity_trapdoor.clone()) } #[wasm_bindgen(js_name = getNullifier)] - pub fn get_nullifier(&self) -> WasmFr { - WasmFr(self.identity_nullifier) + pub fn get_nullifier(&self) -> WasmSecretFr { + WasmSecretFr::from(self.identity_nullifier.clone()) } - #[wasm_bindgen(js_name = getSecretHash)] - pub fn get_secret_hash(&self) -> WasmFr { - WasmFr(self.identity_secret) + #[wasm_bindgen(js_name = getSecret)] + pub fn get_secret(&self) -> WasmSecretFr { + WasmSecretFr::from(self.identity_secret.clone()) } #[wasm_bindgen(js_name = getCommitment)] pub fn get_commitment(&self) -> WasmFr { - WasmFr(self.id_commitment) - } - - #[wasm_bindgen(js_name = toArray)] - pub fn to_array(&self) -> VecWasmFr { - VecWasmFr(vec![ - self.identity_trapdoor, - self.identity_nullifier, - self.identity_secret, - self.id_commitment, - ]) + WasmFr::from(self.id_commitment) } #[wasm_bindgen(js_name = toBytesLE)] pub fn to_bytes_le(&self) -> Result { - let vec_fr = vec![ - self.identity_trapdoor, - self.identity_nullifier, - self.identity_secret, + let vec_fr = Zeroizing::new(vec![ + *self.identity_trapdoor, + *self.identity_nullifier, + *self.identity_secret, self.id_commitment, - ]; + ]); let mut bytes = Vec::new(); vec_fr .serialize_compressed(&mut bytes) @@ -405,45 +417,48 @@ impl ExtendedIdentity { #[wasm_bindgen(js_name = toBytesBE)] pub fn to_bytes_be(&self) -> Result { - let vec_fr = vec![ - self.identity_trapdoor, - self.identity_nullifier, - self.identity_secret, + let vec_fr = Zeroizing::new(vec![ + *self.identity_trapdoor, + *self.identity_nullifier, + *self.identity_secret, self.id_commitment, - ]; + ]); let mut bytes = Vec::new(); - CanonicalSerializeBE::serialize(&vec_fr, &mut bytes).map_err(|err| err.to_string())?; + CanonicalSerializeBE::serialize(&*vec_fr, &mut bytes).map_err(|err| err.to_string())?; Ok(Uint8Array::from(&bytes[..])) } #[wasm_bindgen(js_name = fromBytesLE)] - pub fn from_bytes_le(bytes: &Uint8Array) -> Result { + pub fn from_bytes_le(bytes: &Uint8Array) -> Result { let bytes_vec = bytes.to_vec(); - let vec_fr = - Vec::::deserialize_compressed(&bytes_vec[..]).map_err(|err| err.to_string())?; + let mut vec_fr = Zeroizing::new( + Vec::::deserialize_compressed(&bytes_vec[..]).map_err(|err| err.to_string())?, + ); if vec_fr.len() != 4 { return Err(format!("Expected 4 elements, got {}", vec_fr.len())); } - Ok(ExtendedIdentity { - identity_trapdoor: vec_fr[0], - identity_nullifier: vec_fr[1], - identity_secret: vec_fr[2], + Ok(WasmExtendedIdentityKeys { + identity_trapdoor: SecretFr::from(&mut vec_fr[0]), + identity_nullifier: SecretFr::from(&mut vec_fr[1]), + identity_secret: SecretFr::from(&mut vec_fr[2]), id_commitment: vec_fr[3], }) } #[wasm_bindgen(js_name = fromBytesBE)] - pub fn from_bytes_be(bytes: &Uint8Array) -> Result { + pub fn from_bytes_be(bytes: &Uint8Array) -> Result { let bytes_vec = bytes.to_vec(); - let vec_fr = as CanonicalDeserializeBE>::deserialize(&bytes_vec[..]) - .map_err(|err| err.to_string())?; + let mut vec_fr = Zeroizing::new( + as CanonicalDeserializeBE>::deserialize(&bytes_vec[..]) + .map_err(|err| err.to_string())?, + ); if vec_fr.len() != 4 { return Err(format!("Expected 4 elements, got {}", vec_fr.len())); } - Ok(ExtendedIdentity { - identity_trapdoor: vec_fr[0], - identity_nullifier: vec_fr[1], - identity_secret: vec_fr[2], + Ok(WasmExtendedIdentityKeys { + identity_trapdoor: SecretFr::from(&mut vec_fr[0]), + identity_nullifier: SecretFr::from(&mut vec_fr[1]), + identity_secret: SecretFr::from(&mut vec_fr[2]), id_commitment: vec_fr[3], }) } diff --git a/rln-wasm/tests/browser.rs b/rln-wasm/tests/browser.rs index f1fe32ec..2afebd94 100644 --- a/rln-wasm/tests/browser.rs +++ b/rln-wasm/tests/browser.rs @@ -6,7 +6,7 @@ mod test { use js_sys::{Date, Uint8Array}; use rln::prelude::*; use rln_wasm::{ - Hasher, Identity, VecWasmFr, WasmFr, WasmRLN, WasmRLNPartialProof, + VecWasmFr, WasmFr, WasmHasher, WasmIdentityKeys, WasmRLN, WasmRLNPartialProof, WasmRLNPartialWitnessInput, WasmRLNProof, WasmRLNWitnessInput, }; #[cfg(feature = "parallel")] @@ -40,7 +40,7 @@ mod test { wasm_bindgen_test_configure!(run_in_browser); #[wasm_bindgen_test] - pub async fn rln_wasm_benchmark() { + pub async fn test_wasm_benchmark() { #[cfg(feature = "parallel")] if !isThreadpoolSupported().unwrap() { panic!("Thread pool is NOT supported"); @@ -70,28 +70,28 @@ mod test { // Benchmark generate identity let start_identity_gen = Date::now(); for _ in 0..iterations { - let _ = Identity::generate(); + let _ = WasmIdentityKeys::generate(); } let identity_gen_result = Date::now() - start_identity_gen; // Generate identity for other benchmarks - let identity_pair = Identity::generate(); - let identity_secret = identity_pair.get_secret_hash(); + let identity_pair = WasmIdentityKeys::generate(); + let identity_secret = identity_pair.get_secret(); let id_commitment = identity_pair.get_commitment(); - let epoch = Hasher::hash_to_field_le(&Uint8Array::from(b"test-epoch" as &[u8])); + let epoch = WasmHasher::hash_to_field_le(&Uint8Array::from(b"test-epoch" as &[u8])); let rln_identifier = - Hasher::hash_to_field_le(&Uint8Array::from(b"test-rln-identifier" as &[u8])); - let external_nullifier = Hasher::poseidon_hash_pair(&epoch, &rln_identifier); + WasmHasher::hash_to_field_le(&Uint8Array::from(b"test-rln-identifier" as &[u8])); + let external_nullifier = WasmHasher::poseidon_hash_pair(&epoch, &rln_identifier); let identity_index = tree.leaves_set(); let user_message_limit = WasmFr::from_uint(10); - let rate_commitment = Hasher::poseidon_hash_pair(&id_commitment, &user_message_limit); + let rate_commitment = WasmHasher::poseidon_hash_pair(&id_commitment, &user_message_limit); tree.update_next(*rate_commitment).unwrap(); let message_id = WasmFr::from_uint(0); let signal: [u8; 32] = [0; 32]; - let x = Hasher::hash_to_field_le(&Uint8Array::from(&signal[..])); + let x = WasmHasher::hash_to_field_le(&Uint8Array::from(&signal[..])); let merkle_proof: OptimalMerkleProof = tree.proof(identity_index).unwrap(); let mut path_elements = VecWasmFr::new(); diff --git a/rln-wasm/tests/node.rs b/rln-wasm/tests/node.rs index df5f949d..fd3ea350 100644 --- a/rln-wasm/tests/node.rs +++ b/rln-wasm/tests/node.rs @@ -6,8 +6,9 @@ mod test { use js_sys::{Date, Uint8Array}; use rln::prelude::*; use rln_wasm::{ - Hasher, Identity, VecWasmFr, WasmFr, WasmRLN, WasmRLNPartialProof, + VecWasmFr, WasmFr, WasmHasher, WasmIdentityKeys, WasmRLN, WasmRLNPartialProof, WasmRLNPartialWitnessInput, WasmRLNProof, WasmRLNProofValues, WasmRLNWitnessInput, + WasmSecretFr, }; use wasm_bindgen_test::{console_log, wasm_bindgen_test}; use zerokit_utils::merkle_tree::{ @@ -20,7 +21,7 @@ mod test { const GRAPH_BYTES: &[u8] = include_bytes!("../../rln/resources/tree_depth_20/graph.bin"); fn build_witness_parts() -> ( - WasmFr, + WasmSecretFr, WasmFr, WasmFr, VecWasmFr, @@ -31,23 +32,23 @@ mod test { let mut tree: OptimalMerkleTree = OptimalMerkleTree::default(DEFAULT_TREE_DEPTH).unwrap(); - let identity_pair = Identity::generate(); - let identity_secret = identity_pair.get_secret_hash(); + let identity_pair = WasmIdentityKeys::generate(); + let identity_secret = identity_pair.get_secret(); let id_commitment = identity_pair.get_commitment(); - let epoch = Hasher::hash_to_field_le(&Uint8Array::from(b"test-epoch" as &[u8])); + let epoch = WasmHasher::hash_to_field_le(&Uint8Array::from(b"test-epoch" as &[u8])); let rln_identifier = - Hasher::hash_to_field_le(&Uint8Array::from(b"test-rln-identifier" as &[u8])); - let external_nullifier = Hasher::poseidon_hash_pair(&epoch, &rln_identifier); + WasmHasher::hash_to_field_le(&Uint8Array::from(b"test-rln-identifier" as &[u8])); + let external_nullifier = WasmHasher::poseidon_hash_pair(&epoch, &rln_identifier); let identity_index = tree.leaves_set(); let user_message_limit = WasmFr::from_uint(10); - let rate_commitment = Hasher::poseidon_hash_pair(&id_commitment, &user_message_limit); + let rate_commitment = WasmHasher::poseidon_hash_pair(&id_commitment, &user_message_limit); tree.update_next(*rate_commitment).unwrap(); let message_id = WasmFr::from_uint(0); let signal: [u8; 32] = [0; 32]; - let x = Hasher::hash_to_field_le(&Uint8Array::from(&signal[..])); + let x = WasmHasher::hash_to_field_le(&Uint8Array::from(&signal[..])); let merkle_proof: OptimalMerkleProof = tree.proof(identity_index).unwrap(); let mut path_elements = VecWasmFr::new(); @@ -68,7 +69,7 @@ mod test { } #[wasm_bindgen_test] - pub fn rln_wasm_benchmark() { + pub fn test_wasm_benchmark() { let mut results = String::from("\nBenchmarks:\n"); let iterations = 10; @@ -90,28 +91,28 @@ mod test { // Benchmark generate identity let start_identity_gen = Date::now(); for _ in 0..iterations { - let _ = Identity::generate(); + let _ = WasmIdentityKeys::generate(); } let identity_gen_result = Date::now() - start_identity_gen; // Generate identity for other benchmarks - let identity_pair = Identity::generate(); - let identity_secret = identity_pair.get_secret_hash(); + let identity_pair = WasmIdentityKeys::generate(); + let identity_secret = identity_pair.get_secret(); let id_commitment = identity_pair.get_commitment(); - let epoch = Hasher::hash_to_field_le(&Uint8Array::from(b"test-epoch" as &[u8])); + let epoch = WasmHasher::hash_to_field_le(&Uint8Array::from(b"test-epoch" as &[u8])); let rln_identifier = - Hasher::hash_to_field_le(&Uint8Array::from(b"test-rln-identifier" as &[u8])); - let external_nullifier = Hasher::poseidon_hash_pair(&epoch, &rln_identifier); + WasmHasher::hash_to_field_le(&Uint8Array::from(b"test-rln-identifier" as &[u8])); + let external_nullifier = WasmHasher::poseidon_hash_pair(&epoch, &rln_identifier); let identity_index = tree.leaves_set(); let user_message_limit = WasmFr::from_uint(10); - let rate_commitment = Hasher::poseidon_hash_pair(&id_commitment, &user_message_limit); + let rate_commitment = WasmHasher::poseidon_hash_pair(&id_commitment, &user_message_limit); tree.update_next(*rate_commitment).unwrap(); let message_id = WasmFr::from_uint(0); let signal: [u8; 32] = [0; 32]; - let x = Hasher::hash_to_field_le(&Uint8Array::from(&signal[..])); + let x = WasmHasher::hash_to_field_le(&Uint8Array::from(&signal[..])); let merkle_proof: OptimalMerkleProof = tree.proof(identity_index).unwrap(); let mut path_elements = VecWasmFr::new(); diff --git a/rln-wasm/tests/utils.rs b/rln-wasm/tests/utils.rs index ce075239..6243bfe1 100644 --- a/rln-wasm/tests/utils.rs +++ b/rln-wasm/tests/utils.rs @@ -11,32 +11,34 @@ mod test { use rand::Rng; use rln::prelude::*; use rln_wasm::{ - wasm_utils::Uint8ArrayUtils, ExtendedIdentity, Hasher, Identity, VecWasmFr, WasmFr, + wasm_utils::WasmUint8ArrayUtils, VecWasmFr, WasmExtendedIdentityKeys, WasmFr, WasmHasher, + WasmIdentityKeys, }; 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 identity = WasmIdentityKeys::generate(); + let identity_secret = **identity.get_secret().inner(); 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); + let bytes = identity.to_bytes_le().unwrap(); + let restored = WasmIdentityKeys::from_bytes_le(&bytes).unwrap(); + + assert_eq!(**restored.get_secret().inner(), identity_secret); + assert_eq!(*restored.get_commitment(), id_commitment); } #[wasm_bindgen_test] fn test_extended_keygen_wasm() { - let identity = ExtendedIdentity::generate(); + let identity = WasmExtendedIdentityKeys::generate(); - let identity_trapdoor = *identity.get_trapdoor(); - let identity_nullifier = *identity.get_nullifier(); - let identity_secret = *identity.get_secret_hash(); + let identity_trapdoor = **identity.get_trapdoor().inner(); + let identity_nullifier = **identity.get_nullifier().inner(); + let identity_secret = **identity.get_secret().inner(); let id_commitment = *identity.get_commitment(); assert_ne!(identity_trapdoor, Fr::from(0u8)); @@ -44,12 +46,13 @@ mod test { 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); + let bytes = identity.to_bytes_le().unwrap(); + let restored = WasmExtendedIdentityKeys::from_bytes_le(&bytes).unwrap(); + + assert_eq!(**restored.get_trapdoor().inner(), identity_trapdoor); + assert_eq!(**restored.get_nullifier().inner(), identity_nullifier); + assert_eq!(**restored.get_secret().inner(), identity_secret); + assert_eq!(*restored.get_commitment(), id_commitment); } #[wasm_bindgen_test] @@ -57,8 +60,8 @@ mod test { let seed_bytes: Vec = 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 identity = WasmIdentityKeys::generate_seeded(&seed); + let identity_secret = **identity.get_secret().inner(); let id_commitment = *identity.get_commitment(); let expected_identity_secret_seed_bytes = Fr::from( @@ -85,11 +88,11 @@ mod test { let seed_bytes: Vec = 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 = WasmExtendedIdentityKeys::generate_seeded(&seed); - let identity_trapdoor = *identity.get_trapdoor(); - let identity_nullifier = *identity.get_nullifier(); - let identity_secret = *identity.get_secret_hash(); + let identity_trapdoor = **identity.get_trapdoor().inner(); + let identity_nullifier = **identity.get_nullifier().inner(); + let identity_secret = **identity.get_secret().inner(); let id_commitment = *identity.get_commitment(); let expected_identity_trapdoor_seed_bytes = Fr::from( @@ -144,14 +147,12 @@ mod test { 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 identity = WasmIdentityKeys::generate(); + let id_secret = **identity.get_secret().inner(); 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); + + assert_eq!(**identity.get_secret().inner(), id_secret); + assert_eq!(*identity.get_commitment(), id_commitment); } #[wasm_bindgen_test] @@ -202,15 +203,14 @@ mod test { let signal_gen: [u8; 32] = rng.gen(); let signal = Uint8Array::from(&signal_gen[..]); - let wasmfr_le_1 = Hasher::hash_to_field_le(&signal); + let wasmfr_le_1 = WasmHasher::hash_to_field_le(&signal); let fr_le_2 = 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 wasmfr_be_1 = WasmHasher::hash_to_field_be(&signal); let fr_be_2 = hash_to_field_be(&signal_gen); assert_eq!(*wasmfr_be_1, fr_be_2); - // LE and BE interpret the hash bytes differently assert_ne!(*wasmfr_le_1, *wasmfr_be_1); assert_ne!(fr_le_2, fr_be_2); @@ -233,7 +233,7 @@ mod test { 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); + let received_hash = WasmHasher::poseidon_hash_pair(&wasmfr_1, &wasmfr_2); assert_eq!(*received_hash, expected_hash); } @@ -277,16 +277,16 @@ mod test { #[wasm_bindgen_test] fn test_uint8array_utils_from_bytes_invalid() { let short = Uint8Array::from(&[0u8; 7][..]); - assert!(Uint8ArrayUtils::from_bytes_le(&short).is_err()); - assert!(Uint8ArrayUtils::from_bytes_be(&short).is_err()); + assert!(WasmUint8ArrayUtils::from_bytes_le(&short).is_err()); + assert!(WasmUint8ArrayUtils::from_bytes_be(&short).is_err()); let invalid_len_le = Vec::from(5u64.to_le_bytes()); let invalid_len_le = Uint8Array::from(&invalid_len_le[..]); - assert!(Uint8ArrayUtils::from_bytes_le(&invalid_len_le).is_err()); + assert!(WasmUint8ArrayUtils::from_bytes_le(&invalid_len_le).is_err()); let invalid_len_be = Vec::from(5u64.to_be_bytes()); let invalid_len_be = Uint8Array::from(&invalid_len_be[..]); - assert!(Uint8ArrayUtils::from_bytes_be(&invalid_len_be).is_err()); + assert!(WasmUint8ArrayUtils::from_bytes_be(&invalid_len_be).is_err()); } #[wasm_bindgen_test] @@ -295,12 +295,12 @@ mod test { let mut bytes_le = Vec::new(); vec_fr.serialize_compressed(&mut bytes_le).unwrap(); let bytes_le = Uint8Array::from(&bytes_le[..]); - assert!(Identity::from_bytes_le(&bytes_le).is_err()); + assert!(WasmIdentityKeys::from_bytes_le(&bytes_le).is_err()); let mut bytes_be = Vec::new(); CanonicalSerializeBE::serialize(&vec_fr, &mut bytes_be).unwrap(); let bytes_be = Uint8Array::from(&bytes_be[..]); - assert!(Identity::from_bytes_be(&bytes_be).is_err()); + assert!(WasmIdentityKeys::from_bytes_be(&bytes_be).is_err()); } #[wasm_bindgen_test] @@ -309,11 +309,11 @@ mod test { let mut bytes_le = Vec::new(); vec_fr.serialize_compressed(&mut bytes_le).unwrap(); let bytes_le = Uint8Array::from(&bytes_le[..]); - assert!(ExtendedIdentity::from_bytes_le(&bytes_le).is_err()); + assert!(WasmExtendedIdentityKeys::from_bytes_le(&bytes_le).is_err()); let mut bytes_be = Vec::new(); CanonicalSerializeBE::serialize(&vec_fr, &mut bytes_be).unwrap(); let bytes_be = Uint8Array::from(&bytes_be[..]); - assert!(ExtendedIdentity::from_bytes_be(&bytes_be).is_err()); + assert!(WasmExtendedIdentityKeys::from_bytes_be(&bytes_be).is_err()); } } diff --git a/rln/benches/generate_proof_benchmark.rs b/rln/benches/generate_proof_benchmark.rs index a4f1adb7..a0e6b3a8 100644 --- a/rln/benches/generate_proof_benchmark.rs +++ b/rln/benches/generate_proof_benchmark.rs @@ -34,7 +34,7 @@ fn get_test_witness() -> RLNWitnessInput { .unwrap() } -pub fn rln_proof_benchmark(c: &mut Criterion) { +pub fn generate_proof_benchmark(c: &mut Criterion) { let rln = RLNBuilder::stateless().build(); let witness = get_test_witness(); @@ -60,5 +60,5 @@ pub fn rln_proof_benchmark(c: &mut Criterion) { }); } -criterion_group!(benches, rln_proof_benchmark); +criterion_group!(benches, generate_proof_benchmark); criterion_main!(benches); diff --git a/rln/ffi_c_examples/README.md b/rln/ffi_c_examples/README.md index e0361c56..45717ca0 100644 --- a/rln/ffi_c_examples/README.md +++ b/rln/ffi_c_examples/README.md @@ -41,9 +41,9 @@ gcc -Wall stateless.c -o stateless -lrln -L../../target/release ## Memory ownership -- Every pointer returned by the FFI is owned by the caller and must be released with its matching `ffi_*_free` function (`ffi_cfr_free`, `ffi_rln_proof_free`, `ffi_rln_witness_input_free`, ...). +- Every pointer returned by the FFI is owned by the caller and must be released with its matching `ffi_*_free` function (`ffi_fr_free`, `ffi_rln_proof_free`, `ffi_rln_witness_input_free`, `ffi_identity_keys_free`,...). - Debug and error strings are Rust `Vec`; release them with `ffi_c_string_free`. -- `ffi_vec_cfr_get` returns a borrowed pointer into the vector: do not free it, and do not use it after the vector itself is freed. +- `ffi_vec_fr_get` returns a borrowed pointer into the vector: do not free it, and do not use it after the vector itself is freed. - The examples free everything explicitly to document this contract. ## Notes diff --git a/rln/ffi_c_examples/basic_proof.c b/rln/ffi_c_examples/basic_proof.c index af8f0223..59dc9ab6 100644 --- a/rln/ffi_c_examples/basic_proof.c +++ b/rln/ffi_c_examples/basic_proof.c @@ -20,17 +20,17 @@ int main(void) return EXIT_FAILURE; } - CFr *external_nullifier = compute_external_nullifier(); + Fr *external_nullifier = compute_external_nullifier(); printf("\nHashing signal\n"); uint8_t signal[32] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - CFr *x = hash_signal(signal); - print_cfr("x", x); + Fr *x = hash_signal(signal); + print_fr("x", x); printf("\nCreating message id\n"); - CFr *message_id = ffi_uint_to_cfr(0); - print_cfr("message id", message_id); + Fr *message_id = ffi_uint_to_fr(0); + print_fr("message id", message_id); printf("\nCreating RLN witness\n"); WitnessResult witness_result = @@ -58,34 +58,34 @@ int main(void) printf("\nGetting RLN proof values\n"); ProofValues *proof_values = ffi_rln_proof_get_values(&rln_proof); - CFrResult y_result = ffi_rln_proof_values_get_y(&proof_values); + FrResult y_result = ffi_rln_proof_values_get_y(&proof_values); if (!y_result.ok) { fprintf(stderr, "Get y error: %s\n", y_result.err.ptr); ffi_c_string_free(y_result.err); return EXIT_FAILURE; } - print_cfr("y", y_result.ok); - ffi_cfr_free(y_result.ok); - CFrResult nullifier_result = ffi_rln_proof_values_get_nullifier(&proof_values); + print_fr("y", y_result.ok); + ffi_fr_free(y_result.ok); + FrResult nullifier_result = ffi_rln_proof_values_get_nullifier(&proof_values); if (!nullifier_result.ok) { fprintf(stderr, "Get nullifier error: %s\n", nullifier_result.err.ptr); ffi_c_string_free(nullifier_result.err); return EXIT_FAILURE; } - print_cfr("nullifier", nullifier_result.ok); - ffi_cfr_free(nullifier_result.ok); - CFr *proof_values_root = ffi_rln_proof_values_get_root(&proof_values); - print_cfr("root", proof_values_root); - ffi_cfr_free(proof_values_root); - CFr *proof_values_x = ffi_rln_proof_values_get_x(&proof_values); - print_cfr("x", proof_values_x); - ffi_cfr_free(proof_values_x); - CFr *proof_values_external_nullifier = + print_fr("nullifier", nullifier_result.ok); + ffi_fr_free(nullifier_result.ok); + Fr *proof_values_root = ffi_rln_proof_values_get_root(&proof_values); + print_fr("root", proof_values_root); + ffi_fr_free(proof_values_root); + Fr *proof_values_x = ffi_rln_proof_values_get_x(&proof_values); + print_fr("x", proof_values_x); + ffi_fr_free(proof_values_x); + Fr *proof_values_external_nullifier = ffi_rln_proof_values_get_external_nullifier(&proof_values); - print_cfr("external nullifier", proof_values_external_nullifier); - ffi_cfr_free(proof_values_external_nullifier); + print_fr("external nullifier", proof_values_external_nullifier); + ffi_fr_free(proof_values_external_nullifier); printf("\nVerifying proof\n"); CBoolResult verify_result = verify_stateful_proof(&rln_instance, &rln_proof, x); @@ -108,9 +108,9 @@ int main(void) ffi_rln_proof_values_free(proof_values); ffi_rln_proof_free(rln_proof); ffi_rln_witness_input_free(witness); - ffi_cfr_free(message_id); - ffi_cfr_free(x); - ffi_cfr_free(external_nullifier); + ffi_fr_free(message_id); + ffi_fr_free(x); + ffi_fr_free(external_nullifier); ffi_rln_merkle_proof_free(merkle_proof); member_free(&member); ffi_rln_free(rln_instance); diff --git a/rln/ffi_c_examples/common.c b/rln/ffi_c_examples/common.c index d50a27d1..9ad72917 100644 --- a/rln/ffi_c_examples/common.c +++ b/rln/ffi_c_examples/common.c @@ -5,11 +5,13 @@ #include "rln.h" -typedef CFr_t CFr; -typedef Vec_CFr_t Vec_CFr; +typedef FFI_Fr_t Fr; +typedef FFI_SecretFr_t SecretFr; +typedef FFI_IdentityKeys_t IdentityKeys; +typedef Vec_FFI_Fr_t Vec_Fr; typedef Vec_uint8_t Vec_uint8; typedef Vec_bool_t Vec_bool; -typedef CBoolResult_t CBoolResult; +typedef FFI_BoolResult_t CBoolResult; typedef FFI_RLN_t RLN; typedef FFI_RLNWitnessInput_t Witness; typedef FFI_RLNPartialWitnessInput_t PartialWitness; @@ -17,26 +19,26 @@ typedef FFI_RLNProof_t Proof; typedef FFI_RLNPartialProof_t PartialProof; typedef FFI_RLNProofValues_t ProofValues; typedef FFI_RLNMerkleProof_t MerkleProof; -typedef CResult_FFI_RLN_ptr_Vec_uint8_t RLNResult; -typedef CResult_FFI_RLNWitnessInput_ptr_Vec_uint8_t WitnessResult; -typedef CResult_FFI_RLNPartialWitnessInput_ptr_Vec_uint8_t PartialWitnessResult; -typedef CResult_FFI_RLNProof_ptr_Vec_uint8_t ProofResult; -typedef CResult_FFI_RLNPartialProof_ptr_Vec_uint8_t PartialProofResult; -typedef CResult_FFI_RLNMerkleProof_ptr_Vec_uint8_t MerkleProofResult; -typedef CResult_CFr_ptr_Vec_uint8_t CFrResult; -typedef CResult_Vec_CFr_Vec_uint8_t VecCFrResult; -typedef CResult_Vec_uint8_Vec_uint8_t VecU8Result; +typedef FFI_Result_FFI_RLN_ptr_Vec_uint8_t RLNResult; +typedef FFI_Result_FFI_RLNWitnessInput_ptr_Vec_uint8_t WitnessResult; +typedef FFI_Result_FFI_RLNPartialWitnessInput_ptr_Vec_uint8_t PartialWitnessResult; +typedef FFI_Result_FFI_RLNProof_ptr_Vec_uint8_t ProofResult; +typedef FFI_Result_FFI_RLNPartialProof_ptr_Vec_uint8_t PartialProofResult; +typedef FFI_Result_FFI_RLNMerkleProof_ptr_Vec_uint8_t MerkleProofResult; +typedef FFI_Result_FFI_Fr_ptr_Vec_uint8_t FrResult; +typedef FFI_Result_FFI_SecretFr_ptr_Vec_uint8_t SecretFrResult; +typedef FFI_Result_Vec_FFI_Fr_Vec_uint8_t VecFrResult; +typedef FFI_Result_Vec_uint8_Vec_uint8_t VecU8Result; #define TREE_DEPTH 20 #define MAX_OUT 4 typedef struct { - Vec_CFr keys; - const CFr *identity_secret; - const CFr *id_commitment; - CFr *user_message_limit; - CFr *rate_commitment; + SecretFr *identity_secret; + Fr *id_commitment; + Fr *user_message_limit; + Fr *rate_commitment; } Member; int file_to_bytes(const char *path, Vec_uint8 *out) @@ -63,16 +65,23 @@ int file_to_bytes(const char *path, Vec_uint8 *out) return 0; } -void print_cfr(const char *label, const CFr *value) +void print_fr(const char *label, const Fr *value) { - Vec_uint8 debug = ffi_cfr_debug(value); + Vec_uint8 debug = ffi_fr_debug(value); printf(" - %s = %s\n", label, debug.ptr); ffi_c_string_free(debug); } -void print_vec_cfr(const char *label, const Vec_CFr *value) +void print_secret_fr(const char *label, const SecretFr *value) { - Vec_uint8 debug = ffi_vec_cfr_debug(value); + Vec_uint8 debug = ffi_secret_fr_debug(value); + printf(" - %s = %s\n", label, debug.ptr); + ffi_c_string_free(debug); +} + +void print_vec_fr(const char *label, const Vec_Fr *value) +{ + Vec_uint8 debug = ffi_vec_fr_debug(value); printf(" - %s = %s\n", label, debug.ptr); ffi_c_string_free(debug); } @@ -165,34 +174,37 @@ RLN *init_rln_stateless(void) int create_member(Member *member) { printf("\nGenerating identity keys\n"); - member->keys = ffi_key_gen(); - member->identity_secret = ffi_vec_cfr_get(&member->keys, 0); - member->id_commitment = ffi_vec_cfr_get(&member->keys, 1); + IdentityKeys *keys = ffi_identity_keys_generate(); + member->identity_secret = ffi_identity_keys_get_secret(keys); + member->id_commitment = ffi_identity_keys_get_commitment(keys); + printf(" - identity generated successfully\n"); - print_cfr("identity secret", member->identity_secret); - print_cfr("id commitment", member->id_commitment); + print_secret_fr("identity secret", member->identity_secret); + print_fr("id commitment", member->id_commitment); printf("\nCreating message limit\n"); - member->user_message_limit = ffi_uint_to_cfr(10); - print_cfr("user message limit", member->user_message_limit); + member->user_message_limit = ffi_uint_to_fr(10); + print_fr("user message limit", member->user_message_limit); printf("\nComputing rate commitment\n"); member->rate_commitment = ffi_poseidon_hash_pair(member->id_commitment, member->user_message_limit); - print_cfr("rate commitment", member->rate_commitment); + print_fr("rate commitment", member->rate_commitment); + ffi_identity_keys_free(keys); return 0; } void member_free(Member *member) { - ffi_cfr_free(member->rate_commitment); - ffi_cfr_free(member->user_message_limit); - ffi_vec_cfr_free(member->keys); + ffi_fr_free(member->rate_commitment); + ffi_fr_free(member->user_message_limit); + ffi_secret_fr_free(member->identity_secret); + ffi_fr_free(member->id_commitment); } MerkleProof *register_member(RLN **rln_instance, - const CFr *rate_commitment) + const Fr *rate_commitment) { printf("\nAdding rate commitment to tree\n"); CBoolResult set_leaf_result = ffi_rln_set_next_leaf(rln_instance, rate_commitment); @@ -217,52 +229,52 @@ MerkleProof *register_member(RLN **rln_instance, return merkle_proof_result.ok; } -CFr *hash_signal(const uint8_t signal[32]) +Fr *hash_signal(const uint8_t signal[32]) { return ffi_hash_to_field_le(&(Vec_uint8){(uint8_t *)signal, 32, 32}); } -CFr *compute_external_nullifier(void) +Fr *compute_external_nullifier(void) { printf("\nHashing epoch\n"); const char *epoch_str = "test-epoch"; - CFr *epoch = ffi_hash_to_field_le( + Fr *epoch = ffi_hash_to_field_le( &(Vec_uint8){(uint8_t *)epoch_str, strlen(epoch_str), strlen(epoch_str)}); - print_cfr("epoch", epoch); + print_fr("epoch", epoch); printf("\nHashing RLN identifier\n"); const char *rln_id_str = "test-rln-identifier"; - CFr *rln_identifier = ffi_hash_to_field_le( + Fr *rln_identifier = ffi_hash_to_field_le( &(Vec_uint8){(uint8_t *)rln_id_str, strlen(rln_id_str), strlen(rln_id_str)}); - print_cfr("RLN identifier", rln_identifier); + print_fr("RLN identifier", rln_identifier); printf("\nComputing Poseidon hash for external nullifier\n"); - CFr *external_nullifier = ffi_poseidon_hash_pair(epoch, rln_identifier); - print_cfr("external nullifier", external_nullifier); + Fr *external_nullifier = ffi_poseidon_hash_pair(epoch, rln_identifier); + print_fr("external nullifier", external_nullifier); - ffi_cfr_free(rln_identifier); - ffi_cfr_free(epoch); + ffi_fr_free(rln_identifier); + ffi_fr_free(epoch); return external_nullifier; } WitnessResult create_witness(const Member *member, const MerkleProof *merkle_proof, - const CFr *message_id, const CFr *x, const CFr *external_nullifier) + const Fr *message_id, const Fr *x, const Fr *external_nullifier) { return ffi_rln_witness_input_new_single(member->identity_secret, - member->user_message_limit, message_id, - &merkle_proof->path_elements, - &merkle_proof->path_index, x, - external_nullifier); + member->user_message_limit, message_id, + &merkle_proof->path_elements, + &merkle_proof->path_index, x, + external_nullifier); } CBoolResult -verify_stateful_proof(RLN **rln_instance, Proof **rln_proof, const CFr *x) +verify_stateful_proof(RLN **rln_instance, Proof **rln_proof, const Fr *x) { - CFr *root = ffi_rln_get_root(rln_instance); - Vec_CFr roots = ffi_vec_cfr_from_cfr(root); + Fr *root = ffi_rln_get_root(rln_instance); + Vec_Fr roots = ffi_vec_fr_from_fr(root); CBoolResult result = ffi_rln_verify_with_roots(rln_instance, rln_proof, &roots, x); - ffi_vec_cfr_free(roots); - ffi_cfr_free(root); + ffi_vec_fr_free(roots); + ffi_fr_free(root); return result; } diff --git a/rln/ffi_c_examples/multi_message_id.c b/rln/ffi_c_examples/multi_message_id.c index 50aa01a6..142d42e4 100644 --- a/rln/ffi_c_examples/multi_message_id.c +++ b/rln/ffi_c_examples/multi_message_id.c @@ -3,28 +3,28 @@ #include "common.c" -static Vec_CFr create_message_ids(const unsigned int ids[MAX_OUT]) +static Vec_Fr create_message_ids(const unsigned int ids[MAX_OUT]) { - Vec_CFr message_ids = ffi_vec_cfr_new(MAX_OUT); + Vec_Fr message_ids = ffi_vec_fr_new(MAX_OUT); for (size_t i = 0; i < MAX_OUT; i++) { - CFr *tmp = ffi_uint_to_cfr(ids[i]); - ffi_vec_cfr_push(&message_ids, tmp); - ffi_cfr_free(tmp); + Fr *tmp = ffi_uint_to_fr(ids[i]); + ffi_vec_fr_push(&message_ids, tmp); + ffi_fr_free(tmp); } return message_ids; } static WitnessResult create_multi_witness(const Member *member, const MerkleProof *merkle_proof, - const Vec_CFr *message_ids, bool selector_used[MAX_OUT], const CFr *x, - const CFr *external_nullifier) + const Vec_Fr *message_ids, bool selector_used[MAX_OUT], const Fr *x, + const Fr *external_nullifier) { return ffi_rln_witness_input_new_multi(member->identity_secret, - member->user_message_limit, message_ids, - &merkle_proof->path_elements, - &merkle_proof->path_index, x, external_nullifier, - &(Vec_bool){selector_used, MAX_OUT, MAX_OUT}); + member->user_message_limit, message_ids, + &merkle_proof->path_elements, + &merkle_proof->path_index, x, external_nullifier, + &(Vec_bool){selector_used, MAX_OUT, MAX_OUT}); } int main(void) @@ -44,20 +44,20 @@ int main(void) return EXIT_FAILURE; } - CFr *external_nullifier = compute_external_nullifier(); + Fr *external_nullifier = compute_external_nullifier(); printf("\nHashing first signal\n"); uint8_t signal1[32] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - CFr *x1 = hash_signal(signal1); - print_cfr("x1", x1); + Fr *x1 = hash_signal(signal1); + print_fr("x1", x1); printf("\nCreating first message ids and selector used\n"); printf(" - using 2 out of %d slots\n", MAX_OUT); const unsigned int ids1[MAX_OUT] = {0, 1, 0, 0}; - Vec_CFr message_ids1 = create_message_ids(ids1); + Vec_Fr message_ids1 = create_message_ids(ids1); bool selector_used1[MAX_OUT] = {true, true, false, false}; - print_vec_cfr("message ids", &message_ids1); + print_vec_fr("message ids", &message_ids1); printf("\nCreating first RLN witness\n"); WitnessResult witness1_result = create_multi_witness( @@ -85,16 +85,16 @@ int main(void) printf("\nGetting first RLN proof values\n"); ProofValues *proof_values1 = ffi_rln_proof_get_values(&rln_proof1); - VecCFrResult ys1_result = ffi_rln_proof_values_get_ys(&proof_values1); + VecFrResult ys1_result = ffi_rln_proof_values_get_ys(&proof_values1); if (ys1_result.err.ptr) { fprintf(stderr, "Get ys error: %s\n", ys1_result.err.ptr); ffi_c_string_free(ys1_result.err); return EXIT_FAILURE; } - print_vec_cfr("ys", &ys1_result.ok); - ffi_vec_cfr_free(ys1_result.ok); - VecCFrResult nullifiers1_result = + print_vec_fr("ys", &ys1_result.ok); + ffi_vec_fr_free(ys1_result.ok); + VecFrResult nullifiers1_result = ffi_rln_proof_values_get_nullifiers(&proof_values1); if (nullifiers1_result.err.ptr) { @@ -102,18 +102,18 @@ int main(void) ffi_c_string_free(nullifiers1_result.err); return EXIT_FAILURE; } - print_vec_cfr("nullifiers", &nullifiers1_result.ok); - ffi_vec_cfr_free(nullifiers1_result.ok); - CFr *proof_values1_root = ffi_rln_proof_values_get_root(&proof_values1); - print_cfr("root", proof_values1_root); - ffi_cfr_free(proof_values1_root); - CFr *proof_values1_x = ffi_rln_proof_values_get_x(&proof_values1); - print_cfr("x", proof_values1_x); - ffi_cfr_free(proof_values1_x); - CFr *proof_values1_external_nullifier = + print_vec_fr("nullifiers", &nullifiers1_result.ok); + ffi_vec_fr_free(nullifiers1_result.ok); + Fr *proof_values1_root = ffi_rln_proof_values_get_root(&proof_values1); + print_fr("root", proof_values1_root); + ffi_fr_free(proof_values1_root); + Fr *proof_values1_x = ffi_rln_proof_values_get_x(&proof_values1); + print_fr("x", proof_values1_x); + ffi_fr_free(proof_values1_x); + Fr *proof_values1_external_nullifier = ffi_rln_proof_values_get_external_nullifier(&proof_values1); - print_cfr("external nullifier", proof_values1_external_nullifier); - ffi_cfr_free(proof_values1_external_nullifier); + print_fr("external nullifier", proof_values1_external_nullifier); + ffi_fr_free(proof_values1_external_nullifier); printf("\nVerifying first proof\n"); CBoolResult verify1_result = verify_stateful_proof(&rln_instance, &rln_proof1, x1); @@ -138,16 +138,16 @@ int main(void) printf("\nHashing second signal\n"); uint8_t signal2[32] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - CFr *x2 = hash_signal(signal2); - print_cfr("x2", x2); + Fr *x2 = hash_signal(signal2); + print_fr("x2", x2); printf("\nCreating second message ids and selector used\n"); printf(" - using 2 out of %d slots\n", MAX_OUT); printf(" - duplicated slot id 1\n"); const unsigned int ids2[MAX_OUT] = {1, 0, 3, 0}; - Vec_CFr message_ids2 = create_message_ids(ids2); + Vec_Fr message_ids2 = create_message_ids(ids2); bool selector_used2[MAX_OUT] = {true, false, true, false}; - print_vec_cfr("message ids", &message_ids2); + print_vec_fr("message ids", &message_ids2); printf("\nCreating second RLN witness\n"); WitnessResult witness2_result = create_multi_witness( @@ -187,7 +187,7 @@ int main(void) printf(" - second proof verified successfully\n"); printf("\nRecovering identity secret\n"); - CFrResult recover_result = + SecretFrResult recover_result = ffi_rln_recover_id_secret(&proof_values1, &proof_values2); if (!recover_result.ok) { @@ -195,11 +195,11 @@ int main(void) ffi_c_string_free(recover_result.err); return EXIT_FAILURE; } - CFr *recovered_secret = recover_result.ok; - print_cfr("recovered secret", recovered_secret); - print_cfr("identity secret", member.identity_secret); + SecretFr *recovered_secret = recover_result.ok; + print_secret_fr("recovered secret", recovered_secret); + print_secret_fr("identity secret", member.identity_secret); printf(" - identity recovered successfully\n"); - ffi_cfr_free(recovered_secret); + ffi_secret_fr_free(recovered_secret); } else { @@ -209,14 +209,14 @@ int main(void) ffi_rln_proof_values_free(proof_values2); ffi_rln_proof_free(rln_proof2); ffi_rln_witness_input_free(witness2); - ffi_vec_cfr_free(message_ids2); - ffi_cfr_free(x2); + ffi_vec_fr_free(message_ids2); + ffi_fr_free(x2); ffi_rln_proof_values_free(proof_values1); ffi_rln_proof_free(rln_proof1); ffi_rln_witness_input_free(witness1); - ffi_vec_cfr_free(message_ids1); - ffi_cfr_free(x1); - ffi_cfr_free(external_nullifier); + ffi_vec_fr_free(message_ids1); + ffi_fr_free(x1); + ffi_fr_free(external_nullifier); ffi_rln_merkle_proof_free(merkle_proof); member_free(&member); ffi_rln_free(rln_instance); diff --git a/rln/ffi_c_examples/partial_proof.c b/rln/ffi_c_examples/partial_proof.c index 08dbdf99..79ff1ebc 100644 --- a/rln/ffi_c_examples/partial_proof.c +++ b/rln/ffi_c_examples/partial_proof.c @@ -20,17 +20,17 @@ int main(void) return EXIT_FAILURE; } - CFr *external_nullifier = compute_external_nullifier(); + Fr *external_nullifier = compute_external_nullifier(); printf("\nHashing signal\n"); uint8_t signal[32] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - CFr *x = hash_signal(signal); - print_cfr("x", x); + Fr *x = hash_signal(signal); + print_fr("x", x); printf("\nCreating message id\n"); - CFr *message_id = ffi_uint_to_cfr(0); - print_cfr("message id", message_id); + Fr *message_id = ffi_uint_to_fr(0); + print_fr("message id", message_id); printf("\nCreating RLN witness\n"); WitnessResult witness_result = @@ -45,16 +45,16 @@ int main(void) printf(" - RLN witness created successfully\n"); printf("\nCreating partial witness from witness fields\n"); - CFr *witness_identity_secret = ffi_rln_witness_input_get_identity_secret(&witness); - CFr *witness_user_message_limit = ffi_rln_witness_input_get_user_message_limit(&witness); - Vec_CFr witness_path_elements = ffi_rln_witness_input_get_path_elements(&witness); + SecretFr *witness_identity_secret = ffi_rln_witness_input_get_identity_secret(&witness); + Fr *witness_user_message_limit = ffi_rln_witness_input_get_user_message_limit(&witness); + Vec_Fr witness_path_elements = ffi_rln_witness_input_get_path_elements(&witness); Vec_uint8 witness_path_index = ffi_rln_witness_input_get_identity_path_index(&witness); PartialWitnessResult partial_witness_result = ffi_rln_partial_witness_input_new(witness_identity_secret, witness_user_message_limit, - &witness_path_elements, &witness_path_index); - ffi_cfr_free(witness_identity_secret); - ffi_cfr_free(witness_user_message_limit); - ffi_vec_cfr_free(witness_path_elements); + &witness_path_elements, &witness_path_index); + ffi_secret_fr_free(witness_identity_secret); + ffi_fr_free(witness_user_message_limit); + ffi_vec_fr_free(witness_path_elements); ffi_vec_u8_free(witness_path_index); if (!partial_witness_result.ok) { @@ -111,9 +111,9 @@ int main(void) ffi_rln_partial_proof_free(partial_proof); ffi_rln_partial_witness_input_free(partial_witness); ffi_rln_witness_input_free(witness); - ffi_cfr_free(message_id); - ffi_cfr_free(x); - ffi_cfr_free(external_nullifier); + ffi_fr_free(message_id); + ffi_fr_free(x); + ffi_fr_free(external_nullifier); ffi_rln_merkle_proof_free(merkle_proof); member_free(&member); ffi_rln_free(rln_instance); diff --git a/rln/ffi_c_examples/recover_secret.c b/rln/ffi_c_examples/recover_secret.c index 0adb0563..f19bb1e0 100644 --- a/rln/ffi_c_examples/recover_secret.c +++ b/rln/ffi_c_examples/recover_secret.c @@ -20,17 +20,17 @@ int main(void) return EXIT_FAILURE; } - CFr *external_nullifier = compute_external_nullifier(); + Fr *external_nullifier = compute_external_nullifier(); printf("\nHashing first signal\n"); uint8_t signal1[32] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - CFr *x1 = hash_signal(signal1); - print_cfr("x1", x1); + Fr *x1 = hash_signal(signal1); + print_fr("x1", x1); printf("\nCreating first message id\n"); - CFr *message_id1 = ffi_uint_to_cfr(0); - print_cfr("message id", message_id1); + Fr *message_id1 = ffi_uint_to_fr(0); + print_fr("message id", message_id1); printf("\nCreating first RLN witness\n"); WitnessResult witness1_result = @@ -80,12 +80,12 @@ int main(void) printf("\nHashing second signal\n"); uint8_t signal2[32] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - CFr *x2 = hash_signal(signal2); - print_cfr("x2", x2); + Fr *x2 = hash_signal(signal2); + print_fr("x2", x2); printf("\nCreating second message with the same id\n"); - CFr *message_id2 = ffi_uint_to_cfr(0); - print_cfr("message id", message_id2); + Fr *message_id2 = ffi_uint_to_fr(0); + print_fr("message id", message_id2); printf("\nCreating second RLN witness\n"); WitnessResult witness2_result = @@ -125,7 +125,7 @@ int main(void) printf(" - second proof verified successfully\n"); printf("\nRecovering identity secret\n"); - CFrResult recover_result = + SecretFrResult recover_result = ffi_rln_recover_id_secret(&proof_values1, &proof_values2); if (!recover_result.ok) { @@ -133,11 +133,11 @@ int main(void) ffi_c_string_free(recover_result.err); return EXIT_FAILURE; } - CFr *recovered_secret = recover_result.ok; - print_cfr("recovered secret", recovered_secret); - print_cfr("identity secret", member.identity_secret); + SecretFr *recovered_secret = recover_result.ok; + print_secret_fr("recovered secret", recovered_secret); + print_secret_fr("identity secret", member.identity_secret); printf(" - identity recovered successfully\n"); - ffi_cfr_free(recovered_secret); + ffi_secret_fr_free(recovered_secret); } else { @@ -147,14 +147,14 @@ int main(void) ffi_rln_proof_values_free(proof_values2); ffi_rln_proof_free(rln_proof2); ffi_rln_witness_input_free(witness2); - ffi_cfr_free(message_id2); - ffi_cfr_free(x2); + ffi_fr_free(message_id2); + ffi_fr_free(x2); ffi_rln_proof_values_free(proof_values1); ffi_rln_proof_free(rln_proof1); ffi_rln_witness_input_free(witness1); - ffi_cfr_free(message_id1); - ffi_cfr_free(x1); - ffi_cfr_free(external_nullifier); + ffi_fr_free(message_id1); + ffi_fr_free(x1); + ffi_fr_free(external_nullifier); ffi_rln_merkle_proof_free(merkle_proof); member_free(&member); ffi_rln_free(rln_instance); diff --git a/rln/ffi_c_examples/stateless.c b/rln/ffi_c_examples/stateless.c index ed1b6754..1fe49bd4 100644 --- a/rln/ffi_c_examples/stateless.c +++ b/rln/ffi_c_examples/stateless.c @@ -15,52 +15,52 @@ int main(void) create_member(&member); printf("\nComputing Merkle path for stateless mode\n"); - CFr *default_leaf = ffi_cfr_zero(); - CFr *default_hashes[TREE_DEPTH - 1]; + Fr *default_leaf = ffi_fr_zero(); + Fr *default_hashes[TREE_DEPTH - 1]; default_hashes[0] = ffi_poseidon_hash_pair(default_leaf, default_leaf); for (size_t i = 1; i < TREE_DEPTH - 1; i++) { default_hashes[i] = ffi_poseidon_hash_pair(default_hashes[i - 1], default_hashes[i - 1]); } - Vec_CFr path_elements = ffi_vec_cfr_new(TREE_DEPTH); - ffi_vec_cfr_push(&path_elements, default_leaf); + Vec_Fr path_elements = ffi_vec_fr_new(TREE_DEPTH); + ffi_vec_fr_push(&path_elements, default_leaf); for (size_t i = 1; i < TREE_DEPTH; i++) { - ffi_vec_cfr_push(&path_elements, default_hashes[i - 1]); + ffi_vec_fr_push(&path_elements, default_hashes[i - 1]); } uint8_t path_index_data[TREE_DEPTH] = {0}; Vec_uint8 path_index = {path_index_data, TREE_DEPTH, TREE_DEPTH}; printf("\nComputing Merkle root for stateless mode\n"); printf(" - computing root for index 0 with rate commitment\n"); - CFr *computed_root = ffi_poseidon_hash_pair(member.rate_commitment, default_leaf); + Fr *computed_root = ffi_poseidon_hash_pair(member.rate_commitment, default_leaf); for (size_t i = 1; i < TREE_DEPTH; i++) { - CFr *next_root = ffi_poseidon_hash_pair(computed_root, default_hashes[i - 1]); - ffi_cfr_free(computed_root); + Fr *next_root = ffi_poseidon_hash_pair(computed_root, default_hashes[i - 1]); + ffi_fr_free(computed_root); computed_root = next_root; } - print_cfr("computed root", computed_root); - Vec_CFr roots = ffi_vec_cfr_new(1); - ffi_vec_cfr_push(&roots, computed_root); + print_fr("computed root", computed_root); + Vec_Fr roots = ffi_vec_fr_new(1); + ffi_vec_fr_push(&roots, computed_root); - CFr *external_nullifier = compute_external_nullifier(); + Fr *external_nullifier = compute_external_nullifier(); printf("\nHashing signal\n"); uint8_t signal[32] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - CFr *x = hash_signal(signal); - print_cfr("x", x); + Fr *x = hash_signal(signal); + print_fr("x", x); printf("\nCreating message id\n"); - CFr *message_id = ffi_uint_to_cfr(0); - print_cfr("message id", message_id); + Fr *message_id = ffi_uint_to_fr(0); + print_fr("message id", message_id); printf("\nCreating RLN witness\n"); WitnessResult witness_result = ffi_rln_witness_input_new_single(member.identity_secret, member.user_message_limit, - message_id, &path_elements, &path_index, x, - external_nullifier); + message_id, &path_elements, &path_index, x, + external_nullifier); if (!witness_result.ok) { fprintf(stderr, "Witness creation error: %s\n", witness_result.err.ptr); @@ -84,34 +84,34 @@ int main(void) printf("\nGetting RLN proof values\n"); ProofValues *proof_values = ffi_rln_proof_get_values(&rln_proof); - CFrResult y_result = ffi_rln_proof_values_get_y(&proof_values); + FrResult y_result = ffi_rln_proof_values_get_y(&proof_values); if (!y_result.ok) { fprintf(stderr, "Get y error: %s\n", y_result.err.ptr); ffi_c_string_free(y_result.err); return EXIT_FAILURE; } - print_cfr("y", y_result.ok); - ffi_cfr_free(y_result.ok); - CFrResult nullifier_result = ffi_rln_proof_values_get_nullifier(&proof_values); + print_fr("y", y_result.ok); + ffi_fr_free(y_result.ok); + FrResult nullifier_result = ffi_rln_proof_values_get_nullifier(&proof_values); if (!nullifier_result.ok) { fprintf(stderr, "Get nullifier error: %s\n", nullifier_result.err.ptr); ffi_c_string_free(nullifier_result.err); return EXIT_FAILURE; } - print_cfr("nullifier", nullifier_result.ok); - ffi_cfr_free(nullifier_result.ok); - CFr *proof_values_root = ffi_rln_proof_values_get_root(&proof_values); - print_cfr("root", proof_values_root); - ffi_cfr_free(proof_values_root); - CFr *proof_values_x = ffi_rln_proof_values_get_x(&proof_values); - print_cfr("x", proof_values_x); - ffi_cfr_free(proof_values_x); - CFr *proof_values_external_nullifier = + print_fr("nullifier", nullifier_result.ok); + ffi_fr_free(nullifier_result.ok); + Fr *proof_values_root = ffi_rln_proof_values_get_root(&proof_values); + print_fr("root", proof_values_root); + ffi_fr_free(proof_values_root); + Fr *proof_values_x = ffi_rln_proof_values_get_x(&proof_values); + print_fr("x", proof_values_x); + ffi_fr_free(proof_values_x); + Fr *proof_values_external_nullifier = ffi_rln_proof_values_get_external_nullifier(&proof_values); - print_cfr("external nullifier", proof_values_external_nullifier); - ffi_cfr_free(proof_values_external_nullifier); + print_fr("external nullifier", proof_values_external_nullifier); + ffi_fr_free(proof_values_external_nullifier); printf("\nVerifying proof\n"); CBoolResult verify_result = @@ -135,17 +135,17 @@ int main(void) ffi_rln_proof_values_free(proof_values); ffi_rln_proof_free(rln_proof); ffi_rln_witness_input_free(witness); - ffi_cfr_free(message_id); - ffi_cfr_free(x); - ffi_cfr_free(external_nullifier); - ffi_vec_cfr_free(roots); - ffi_cfr_free(computed_root); - ffi_vec_cfr_free(path_elements); + ffi_fr_free(message_id); + ffi_fr_free(x); + ffi_fr_free(external_nullifier); + ffi_vec_fr_free(roots); + ffi_fr_free(computed_root); + ffi_vec_fr_free(path_elements); for (size_t i = 0; i < TREE_DEPTH - 1; i++) { - ffi_cfr_free(default_hashes[i]); + ffi_fr_free(default_hashes[i]); } - ffi_cfr_free(default_leaf); + ffi_fr_free(default_leaf); member_free(&member); ffi_rln_free(rln_instance); return EXIT_SUCCESS; diff --git a/rln/ffi_c_examples/type_serialization.c b/rln/ffi_c_examples/type_serialization.c index 592f0799..053c5d19 100644 --- a/rln/ffi_c_examples/type_serialization.c +++ b/rln/ffi_c_examples/type_serialization.c @@ -20,17 +20,17 @@ int main(void) return EXIT_FAILURE; } - CFr *external_nullifier = compute_external_nullifier(); + Fr *external_nullifier = compute_external_nullifier(); printf("\nHashing signal\n"); uint8_t signal[32] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - CFr *x = hash_signal(signal); - print_cfr("x", x); + Fr *x = hash_signal(signal); + print_fr("x", x); printf("\nCreating message id\n"); - CFr *message_id = ffi_uint_to_cfr(0); - print_cfr("message id", message_id); + Fr *message_id = ffi_uint_to_fr(0); + print_fr("message id", message_id); printf("\nCreating RLN witness\n"); WitnessResult witness_result = @@ -122,9 +122,9 @@ int main(void) ffi_rln_witness_input_free(deser_witness); ffi_vec_u8_free(ser_witness); ffi_rln_witness_input_free(witness); - ffi_cfr_free(message_id); - ffi_cfr_free(x); - ffi_cfr_free(external_nullifier); + ffi_fr_free(message_id); + ffi_fr_free(x); + ffi_fr_free(external_nullifier); ffi_rln_merkle_proof_free(merkle_proof); member_free(&member); ffi_rln_free(rln_instance); diff --git a/rln/ffi_nim_examples/README.md b/rln/ffi_nim_examples/README.md index f191ace5..a391401a 100644 --- a/rln/ffi_nim_examples/README.md +++ b/rln/ffi_nim_examples/README.md @@ -32,6 +32,7 @@ This produces the shared library in `target/release`: From this directory: ```bash +cd rln/ffi_nim_examples/ nim c -d:release basic_proof.nim nim c -d:release type_serialization.nim nim c -d:release recover_secret.nim @@ -48,9 +49,9 @@ nim c -d:release stateless.nim ## Memory ownership -- Every pointer returned by the FFI is owned by the caller and must be released with its matching `ffi_*_free` function (`ffi_cfr_free`, `ffi_rln_proof_free`, `ffi_rln_witness_input_free`, ...). +- Every pointer returned by the FFI is owned by the caller and must be released with its matching `ffi_*_free` function (`ffi_fr_free`, `ffi_rln_proof_free`, `ffi_rln_witness_input_free`, `ffi_identity_keys_free`,...). - Debug and error strings are Rust `Vec`; release them with `ffi_c_string_free`. -- `ffi_vec_cfr_get` returns a borrowed pointer into the vector: do not free it, and do not use it after the vector itself is freed. +- `ffi_vec_fr_get` returns a borrowed pointer into the vector: do not free it, and do not use it after the vector itself is freed. - The examples free everything explicitly to document this contract. ## Notes diff --git a/rln/ffi_nim_examples/basic_proof.nim b/rln/ffi_nim_examples/basic_proof.nim index 7f27a254..65445dbe 100644 --- a/rln/ffi_nim_examples/basic_proof.nim +++ b/rln/ffi_nim_examples/basic_proof.nim @@ -17,11 +17,11 @@ proc main() = var signal: array[32, uint8] = [1'u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] let x = hashSignal(signal) - printCfr("x", x) + printFr("x", x) echo "\nCreating message id" - let messageId = ffi_uint_to_cfr(0'u32) - printCfr("message id", messageId) + let messageId = ffi_uint_to_fr(0'u32) + printFr("message id", messageId) echo "\nCreating RLN witness" let witnessResult = createWitness(member, merkleProof, messageId, x, @@ -49,25 +49,25 @@ proc main() = stderr.writeLine("Get y error: " & asString(yResult.err)) ffi_c_string_free(yResult.err) return - printCfr("y", yResult.ok) - ffi_cfr_free(yResult.ok) + printFr("y", yResult.ok) + ffi_fr_free(yResult.ok) let nullifierResult = ffi_rln_proof_values_get_nullifier(addr proofValues) if nullifierResult.ok.isNil: stderr.writeLine("Get nullifier error: " & asString(nullifierResult.err)) ffi_c_string_free(nullifierResult.err) return - printCfr("nullifier", nullifierResult.ok) - ffi_cfr_free(nullifierResult.ok) + printFr("nullifier", nullifierResult.ok) + ffi_fr_free(nullifierResult.ok) let proofValuesRoot = ffi_rln_proof_values_get_root(addr proofValues) - printCfr("root", proofValuesRoot) - ffi_cfr_free(proofValuesRoot) + printFr("root", proofValuesRoot) + ffi_fr_free(proofValuesRoot) let proofValuesX = ffi_rln_proof_values_get_x(addr proofValues) - printCfr("x", proofValuesX) - ffi_cfr_free(proofValuesX) + printFr("x", proofValuesX) + ffi_fr_free(proofValuesX) let proofValuesExternalNullifier = ffi_rln_proof_values_get_external_nullifier(addr proofValues) - printCfr("external nullifier", proofValuesExternalNullifier) - ffi_cfr_free(proofValuesExternalNullifier) + printFr("external nullifier", proofValuesExternalNullifier) + ffi_fr_free(proofValuesExternalNullifier) echo "\nVerifying proof" let verifyResult = verifyStatefulProof(rlnInstance, rlnProof, x) @@ -84,9 +84,9 @@ proc main() = ffi_rln_proof_values_free(proofValues) ffi_rln_proof_free(rlnProof) ffi_rln_witness_input_free(witness) - ffi_cfr_free(messageId) - ffi_cfr_free(x) - ffi_cfr_free(externalNullifier) + ffi_fr_free(messageId) + ffi_fr_free(x) + ffi_fr_free(externalNullifier) ffi_rln_merkle_proof_free(merkleProof) memberFree(member) ffi_rln_free(rlnInstance) diff --git a/rln/ffi_nim_examples/common.nim b/rln/ffi_nim_examples/common.nim index d55ecc35..0d087a37 100644 --- a/rln/ffi_nim_examples/common.nim +++ b/rln/ffi_nim_examples/common.nim @@ -4,19 +4,23 @@ const treeDepth = 20 const maxOut = 4 type Member = object - keys: Vec_CFr - identitySecret: ptr CFr - idCommitment: ptr CFr - userMessageLimit: ptr CFr - rateCommitment: ptr CFr - -proc printCfr(label: string, value: ptr CFr) = - let debug = ffi_cfr_debug(value) + identitySecret: ptr SecretFr + idCommitment: ptr Fr + userMessageLimit: ptr Fr + rateCommitment: ptr Fr + +proc printFr(label: string, value: ptr Fr) = + let debug = ffi_fr_debug(value) + echo " - " & label & " = " & asString(debug) + ffi_c_string_free(debug) + +proc printSecretFr(label: string, value: ptr SecretFr) = + let debug = ffi_secret_fr_debug(value) echo " - " & label & " = " & asString(debug) ffi_c_string_free(debug) -proc printVecCfr(label: string, value: ptr Vec_CFr) = - let debug = ffi_vec_cfr_debug(value) +proc printVecFr(label: string, value: ptr Vec_Fr) = + let debug = ffi_vec_fr_debug(value) echo " - " & label & " = " & asString(debug) ffi_c_string_free(debug) @@ -74,29 +78,31 @@ proc initRLNStateless(): ptr RLN = proc createMember(): Member = echo "\nGenerating identity keys" - result.keys = ffi_key_gen() - result.identitySecret = ffi_vec_cfr_get(addr result.keys, csize_t(0)) - result.idCommitment = ffi_vec_cfr_get(addr result.keys, csize_t(1)) + let keys = ffi_identity_keys_generate() + result.identitySecret = ffi_identity_keys_get_secret(keys) + result.idCommitment = ffi_identity_keys_get_commitment(keys) + ffi_identity_keys_free(keys) echo " - identity generated successfully" - printCfr("identity secret", result.identitySecret) - printCfr("id commitment", result.idCommitment) + printSecretFr("identity secret", result.identitySecret) + printFr("id commitment", result.idCommitment) echo "\nCreating message limit" - result.userMessageLimit = ffi_uint_to_cfr(10'u32) - printCfr("user message limit", result.userMessageLimit) + result.userMessageLimit = ffi_uint_to_fr(10'u32) + printFr("user message limit", result.userMessageLimit) echo "\nComputing rate commitment" result.rateCommitment = ffi_poseidon_hash_pair(result.idCommitment, result.userMessageLimit) - printCfr("rate commitment", result.rateCommitment) + printFr("rate commitment", result.rateCommitment) proc memberFree(member: var Member) = - ffi_cfr_free(member.rateCommitment) - ffi_cfr_free(member.userMessageLimit) - ffi_vec_cfr_free(member.keys) + ffi_fr_free(member.rateCommitment) + ffi_fr_free(member.userMessageLimit) + ffi_secret_fr_free(member.identitySecret) + ffi_fr_free(member.idCommitment) proc registerMember(rlnInstance: var ptr RLN, - rateCommitment: ptr CFr): ptr MerkleProof = + rateCommitment: ptr Fr): ptr MerkleProof = echo "\nAdding rate commitment to tree" let setLeafResult = ffi_rln_set_next_leaf(addr rlnInstance, rateCommitment) if not setLeafResult.ok: @@ -116,45 +122,46 @@ proc registerMember(rlnInstance: var ptr RLN, echo " - merkle proof obtained" merkleProofResult.ok -proc hashSignal(signal: var array[32, uint8]): ptr CFr = +proc hashSignal(signal: var array[32, uint8]): ptr Fr = var signalVec = Vec_uint8(dataPtr: addr signal[0], len: csize_t(32), cap: csize_t(32)) ffi_hash_to_field_le(addr signalVec) -proc computeExternalNullifier(): ptr CFr = +proc computeExternalNullifier(): ptr Fr = echo "\nHashing epoch" let epochStr = "test-epoch" var epochBuf = strToBytes(epochStr) var epochVec = asVecU8(epochBuf) let epoch = ffi_hash_to_field_le(addr epochVec) - printCfr("epoch", epoch) + printFr("epoch", epoch) echo "\nHashing RLN identifier" let rlnIdStr = "test-rln-identifier" var rlnIdBuf = strToBytes(rlnIdStr) var rlnIdVec = asVecU8(rlnIdBuf) let rlnIdentifier = ffi_hash_to_field_le(addr rlnIdVec) - printCfr("RLN identifier", rlnIdentifier) + printFr("RLN identifier", rlnIdentifier) echo "\nComputing Poseidon hash for external nullifier" let externalNullifier = ffi_poseidon_hash_pair(epoch, rlnIdentifier) - printCfr("external nullifier", externalNullifier) + printFr("external nullifier", externalNullifier) - ffi_cfr_free(rlnIdentifier) - ffi_cfr_free(epoch) + ffi_fr_free(rlnIdentifier) + ffi_fr_free(epoch) externalNullifier proc createWitness(member: Member, - merkleProof: ptr MerkleProof, messageId: ptr CFr, x: ptr CFr, - externalNullifier: ptr CFr): WitnessResult = + merkleProof: ptr MerkleProof, messageId: ptr Fr, x: ptr Fr, + externalNullifier: ptr Fr): WitnessResult = ffi_rln_witness_input_new_single(member.identitySecret, member.userMessageLimit, messageId, addr merkleProof.path_elements, addr merkleProof.path_index, x, externalNullifier) proc verifyStatefulProof(rlnInstance: var ptr RLN, rlnProof: var ptr Proof, - x: ptr CFr): CBoolResult = + x: ptr Fr): CBoolResult = let root = ffi_rln_get_root(addr rlnInstance) - var roots = ffi_vec_cfr_from_cfr(root) - result = ffi_rln_verify_with_roots(addr rlnInstance, addr rlnProof, addr roots, x) - ffi_vec_cfr_free(roots) - ffi_cfr_free(root) + var roots = ffi_vec_fr_from_fr(root) + result = ffi_rln_verify_with_roots(addr rlnInstance, addr rlnProof, + addr roots, x) + ffi_vec_fr_free(roots) + ffi_fr_free(root) diff --git a/rln/ffi_nim_examples/multi_message_id.nim b/rln/ffi_nim_examples/multi_message_id.nim index b0d66fb7..2db76d34 100644 --- a/rln/ffi_nim_examples/multi_message_id.nim +++ b/rln/ffi_nim_examples/multi_message_id.nim @@ -1,16 +1,16 @@ include "common" -proc createMessageIds(ids: array[maxOut, uint32]): Vec_CFr = - result = ffi_vec_cfr_new(csize_t(maxOut)) +proc createMessageIds(ids: array[maxOut, uint32]): Vec_Fr = + result = ffi_vec_fr_new(csize_t(maxOut)) for id in ids: - let tmp = ffi_uint_to_cfr(id) - ffi_vec_cfr_push(addr result, tmp) - ffi_cfr_free(tmp) + let tmp = ffi_uint_to_fr(id) + ffi_vec_fr_push(addr result, tmp) + ffi_fr_free(tmp) proc createMultiWitness(member: Member, - merkleProof: ptr MerkleProof, messageIds: ptr Vec_CFr, - selectorUsed: var array[maxOut, bool], x: ptr CFr, - externalNullifier: ptr CFr): WitnessResult = + merkleProof: ptr MerkleProof, messageIds: ptr Vec_Fr, + selectorUsed: var array[maxOut, bool], x: ptr Fr, + externalNullifier: ptr Fr): WitnessResult = var selectorVec = Vec_bool(dataPtr: addr selectorUsed[0], len: csize_t(maxOut), cap: csize_t(maxOut)) ffi_rln_witness_input_new_multi(member.identitySecret, @@ -34,13 +34,13 @@ proc main() = var signal1: array[32, uint8] = [1'u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] let x1 = hashSignal(signal1) - printCfr("x1", x1) + printFr("x1", x1) echo "\nCreating first message ids and selector used" echo " - using 2 out of " & $maxOut & " slots" var messageIds1 = createMessageIds([0'u32, 1, 0, 0]) var selectorUsed1 = [true, true, false, false] - printVecCfr("message ids", addr messageIds1) + printVecFr("message ids", addr messageIds1) echo "\nCreating first RLN witness" let witness1Result = createMultiWitness(member, merkleProof, @@ -70,26 +70,26 @@ proc main() = ffi_c_string_free(ys1Result.err) return var ys1 = ys1Result.ok - printVecCfr("ys", addr ys1) - ffi_vec_cfr_free(ys1) + printVecFr("ys", addr ys1) + ffi_vec_fr_free(ys1) let nullifiers1Result = ffi_rln_proof_values_get_nullifiers(addr proofValues1) if nullifiers1Result.err.dataPtr != nil: stderr.writeLine("Get nullifiers error: " & asString(nullifiers1Result.err)) ffi_c_string_free(nullifiers1Result.err) return var nullifiers1 = nullifiers1Result.ok - printVecCfr("nullifiers", addr nullifiers1) - ffi_vec_cfr_free(nullifiers1) + printVecFr("nullifiers", addr nullifiers1) + ffi_vec_fr_free(nullifiers1) let proofValues1Root = ffi_rln_proof_values_get_root(addr proofValues1) - printCfr("root", proofValues1Root) - ffi_cfr_free(proofValues1Root) + printFr("root", proofValues1Root) + ffi_fr_free(proofValues1Root) let proofValues1X = ffi_rln_proof_values_get_x(addr proofValues1) - printCfr("x", proofValues1X) - ffi_cfr_free(proofValues1X) + printFr("x", proofValues1X) + ffi_fr_free(proofValues1X) let proofValues1ExternalNullifier = ffi_rln_proof_values_get_external_nullifier(addr proofValues1) - printCfr("external nullifier", proofValues1ExternalNullifier) - ffi_cfr_free(proofValues1ExternalNullifier) + printFr("external nullifier", proofValues1ExternalNullifier) + ffi_fr_free(proofValues1ExternalNullifier) echo "\nVerifying first proof" let verify1Result = verifyStatefulProof(rlnInstance, rlnProof1, x1) @@ -109,14 +109,14 @@ proc main() = var signal2: array[32, uint8] = [11'u8, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] let x2 = hashSignal(signal2) - printCfr("x2", x2) + printFr("x2", x2) echo "\nCreating second message ids and selector used" echo " - using 2 out of " & $maxOut & " slots" echo " - duplicated slot id 1" var messageIds2 = createMessageIds([1'u32, 0, 3, 0]) var selectorUsed2 = [true, false, true, false] - printVecCfr("message ids", addr messageIds2) + printVecFr("message ids", addr messageIds2) echo "\nCreating second RLN witness" let witness2Result = createMultiWitness(member, merkleProof, @@ -158,24 +158,24 @@ proc main() = ffi_c_string_free(recoverResult.err) return let recoveredSecret = recoverResult.ok - printCfr("recovered secret", recoveredSecret) - printCfr("identity secret", member.identitySecret) + printSecretFr("recovered secret", recoveredSecret) + printSecretFr("identity secret", member.identitySecret) echo " - identity recovered successfully" - ffi_cfr_free(recoveredSecret) + ffi_secret_fr_free(recoveredSecret) else: echo "Second proof verification failed" ffi_rln_proof_values_free(proofValues2) ffi_rln_proof_free(rlnProof2) ffi_rln_witness_input_free(witness2) - ffi_vec_cfr_free(messageIds2) - ffi_cfr_free(x2) + ffi_vec_fr_free(messageIds2) + ffi_fr_free(x2) ffi_rln_proof_values_free(proofValues1) ffi_rln_proof_free(rlnProof1) ffi_rln_witness_input_free(witness1) - ffi_vec_cfr_free(messageIds1) - ffi_cfr_free(x1) - ffi_cfr_free(externalNullifier) + ffi_vec_fr_free(messageIds1) + ffi_fr_free(x1) + ffi_fr_free(externalNullifier) ffi_rln_merkle_proof_free(merkleProof) memberFree(member) ffi_rln_free(rlnInstance) diff --git a/rln/ffi_nim_examples/partial_proof.nim b/rln/ffi_nim_examples/partial_proof.nim index 8486068a..105467e8 100644 --- a/rln/ffi_nim_examples/partial_proof.nim +++ b/rln/ffi_nim_examples/partial_proof.nim @@ -17,11 +17,11 @@ proc main() = var signal: array[32, uint8] = [1'u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] let x = hashSignal(signal) - printCfr("x", x) + printFr("x", x) echo "\nCreating message id" - let messageId = ffi_uint_to_cfr(0'u32) - printCfr("message id", messageId) + let messageId = ffi_uint_to_fr(0'u32) + printFr("message id", messageId) echo "\nCreating RLN witness" let witnessResult = createWitness(member, merkleProof, messageId, x, @@ -41,9 +41,9 @@ proc main() = let partialWitnessResult = ffi_rln_partial_witness_input_new( witnessIdentitySecret, witnessUserMessageLimit, addr witnessPathElements, addr witnessPathIndex) - ffi_cfr_free(witnessIdentitySecret) - ffi_cfr_free(witnessUserMessageLimit) - ffi_vec_cfr_free(witnessPathElements) + ffi_secret_fr_free(witnessIdentitySecret) + ffi_fr_free(witnessUserMessageLimit) + ffi_vec_fr_free(witnessPathElements) ffi_vec_u8_free(witnessPathIndex) if partialWitnessResult.ok.isNil: stderr.writeLine("Partial witness creation error: " & asString( @@ -91,9 +91,9 @@ proc main() = ffi_rln_partial_proof_free(partialProof) ffi_rln_partial_witness_input_free(partialWitness) ffi_rln_witness_input_free(witness) - ffi_cfr_free(messageId) - ffi_cfr_free(x) - ffi_cfr_free(externalNullifier) + ffi_fr_free(messageId) + ffi_fr_free(x) + ffi_fr_free(externalNullifier) ffi_rln_merkle_proof_free(merkleProof) memberFree(member) ffi_rln_free(rlnInstance) diff --git a/rln/ffi_nim_examples/recover_secret.nim b/rln/ffi_nim_examples/recover_secret.nim index f9098e23..891fc562 100644 --- a/rln/ffi_nim_examples/recover_secret.nim +++ b/rln/ffi_nim_examples/recover_secret.nim @@ -17,11 +17,11 @@ proc main() = var signal1: array[32, uint8] = [1'u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] let x1 = hashSignal(signal1) - printCfr("x1", x1) + printFr("x1", x1) echo "\nCreating first message id" - let messageId1 = ffi_uint_to_cfr(0'u32) - printCfr("message id", messageId1) + let messageId1 = ffi_uint_to_fr(0'u32) + printFr("message id", messageId1) echo "\nCreating first RLN witness" let witness1Result = createWitness(member, merkleProof, messageId1, x1, @@ -62,11 +62,11 @@ proc main() = var signal2: array[32, uint8] = [11'u8, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] let x2 = hashSignal(signal2) - printCfr("x2", x2) + printFr("x2", x2) echo "\nCreating second message with the same id" - let messageId2 = ffi_uint_to_cfr(0'u32) - printCfr("message id", messageId2) + let messageId2 = ffi_uint_to_fr(0'u32) + printFr("message id", messageId2) echo "\nCreating second RLN witness" let witness2Result = createWitness(member, merkleProof, messageId2, x2, @@ -108,24 +108,24 @@ proc main() = ffi_c_string_free(recoverResult.err) return let recoveredSecret = recoverResult.ok - printCfr("recovered secret", recoveredSecret) - printCfr("identity secret", member.identitySecret) + printSecretFr("recovered secret", recoveredSecret) + printSecretFr("identity secret", member.identitySecret) echo " - identity recovered successfully" - ffi_cfr_free(recoveredSecret) + ffi_secret_fr_free(recoveredSecret) else: echo "Second proof verification failed" ffi_rln_proof_values_free(proofValues2) ffi_rln_proof_free(rlnProof2) ffi_rln_witness_input_free(witness2) - ffi_cfr_free(messageId2) - ffi_cfr_free(x2) + ffi_fr_free(messageId2) + ffi_fr_free(x2) ffi_rln_proof_values_free(proofValues1) ffi_rln_proof_free(rlnProof1) ffi_rln_witness_input_free(witness1) - ffi_cfr_free(messageId1) - ffi_cfr_free(x1) - ffi_cfr_free(externalNullifier) + ffi_fr_free(messageId1) + ffi_fr_free(x1) + ffi_fr_free(externalNullifier) ffi_rln_merkle_proof_free(merkleProof) memberFree(member) ffi_rln_free(rlnInstance) diff --git a/rln/ffi_nim_examples/rln.nim b/rln/ffi_nim_examples/rln.nim index ed2cf4d1..8ff7e5a6 100644 --- a/rln/ffi_nim_examples/rln.nim +++ b/rln/ffi_nim_examples/rln.nim @@ -17,7 +17,8 @@ else: # FFI objects type CSize* = csize_t - CFr* = object + Fr* = object + SecretFr* = object RLN* = object Proof* = object PartialProof* = object @@ -25,8 +26,8 @@ type PartialWitness* = object ProofValues* = object - Vec_CFr* = object - dataPtr*: ptr CFr + Vec_Fr* = object + dataPtr*: ptr Fr len*: CSize cap*: CSize @@ -46,9 +47,19 @@ type cap*: CSize MerkleProof* = object - path_elements*: Vec_CFr + path_elements*: Vec_Fr path_index*: Vec_uint8 + IdentityKeys* = object + identity_secret*: ptr SecretFr + id_commitment*: ptr Fr + + ExtendedIdentityKeys* = object + identity_trapdoor*: ptr SecretFr + identity_nullifier*: ptr SecretFr + identity_secret*: ptr SecretFr + id_commitment*: ptr Fr + CBoolResult* = object ok*: bool err*: Vec_uint8 @@ -81,12 +92,24 @@ type ok*: ptr MerkleProof err*: Vec_uint8 - CFrResult* = object - ok*: ptr CFr + IdentityKeysResult* = object + ok*: ptr IdentityKeys + err*: Vec_uint8 + + ExtendedIdentityKeysResult* = object + ok*: ptr ExtendedIdentityKeys + err*: Vec_uint8 + + FrResult* = object + ok*: ptr Fr err*: Vec_uint8 - VecCFrResult* = object - ok*: Vec_CFr + SecretFrResult* = object + ok*: ptr SecretFr + err*: Vec_uint8 + + VecFrResult* = object + ok*: Vec_Fr err*: Vec_uint8 VecU8Result* = object @@ -101,47 +124,47 @@ type ok*: Vec_size err*: Vec_uint8 -# CFr functions -proc ffi_cfr_zero*(): ptr CFr {.importc: "ffi_cfr_zero", cdecl, +# Fr functions +proc ffi_fr_zero*(): ptr Fr {.importc: "ffi_fr_zero", cdecl, dynlib: RLN_LIB.} -proc ffi_cfr_one*(): ptr CFr {.importc: "ffi_cfr_one", cdecl, dynlib: RLN_LIB.} -proc ffi_cfr_to_bytes_le*(cfr: ptr CFr): VecU8Result {.importc: "ffi_cfr_to_bytes_le", +proc ffi_fr_one*(): ptr Fr {.importc: "ffi_fr_one", cdecl, dynlib: RLN_LIB.} +proc ffi_fr_to_bytes_le*(fr: ptr Fr): VecU8Result {.importc: "ffi_fr_to_bytes_le", cdecl, dynlib: RLN_LIB.} -proc ffi_cfr_to_bytes_be*(cfr: ptr CFr): VecU8Result {.importc: "ffi_cfr_to_bytes_be", +proc ffi_fr_to_bytes_be*(fr: ptr Fr): VecU8Result {.importc: "ffi_fr_to_bytes_be", cdecl, dynlib: RLN_LIB.} -proc ffi_bytes_le_to_cfr*(bytes: ptr Vec_uint8): CFrResult {.importc: "ffi_bytes_le_to_cfr", +proc ffi_bytes_le_to_fr*(bytes: ptr Vec_uint8): FrResult {.importc: "ffi_bytes_le_to_fr", cdecl, dynlib: RLN_LIB.} -proc ffi_bytes_be_to_cfr*(bytes: ptr Vec_uint8): CFrResult {.importc: "ffi_bytes_be_to_cfr", +proc ffi_bytes_be_to_fr*(bytes: ptr Vec_uint8): FrResult {.importc: "ffi_bytes_be_to_fr", cdecl, dynlib: RLN_LIB.} -proc ffi_uint_to_cfr*(value: uint32): ptr CFr {.importc: "ffi_uint_to_cfr", +proc ffi_uint_to_fr*(value: uint32): ptr Fr {.importc: "ffi_uint_to_fr", cdecl, dynlib: RLN_LIB.} -proc ffi_cfr_debug*(cfr: ptr CFr): Vec_uint8 {.importc: "ffi_cfr_debug", cdecl, +proc ffi_fr_debug*(fr: ptr Fr): Vec_uint8 {.importc: "ffi_fr_debug", cdecl, dynlib: RLN_LIB.} -proc ffi_cfr_free*(x: ptr CFr) {.importc: "ffi_cfr_free", cdecl, +proc ffi_fr_free*(x: ptr Fr) {.importc: "ffi_fr_free", cdecl, dynlib: RLN_LIB.} -# Vec functions -proc ffi_vec_cfr_new*(capacity: CSize): Vec_CFr {.importc: "ffi_vec_cfr_new", +# Vec functions +proc ffi_vec_fr_new*(capacity: CSize): Vec_Fr {.importc: "ffi_vec_fr_new", cdecl, dynlib: RLN_LIB.} -proc ffi_vec_cfr_from_cfr*(cfr: ptr CFr): Vec_CFr {.importc: "ffi_vec_cfr_from_cfr", +proc ffi_vec_fr_from_fr*(fr: ptr Fr): Vec_Fr {.importc: "ffi_vec_fr_from_fr", cdecl, dynlib: RLN_LIB.} -proc ffi_vec_cfr_push*(v: ptr Vec_CFr, cfr: ptr CFr) {.importc: "ffi_vec_cfr_push", +proc ffi_vec_fr_push*(v: ptr Vec_Fr, fr: ptr Fr) {.importc: "ffi_vec_fr_push", cdecl, dynlib: RLN_LIB.} -proc ffi_vec_cfr_len*(v: ptr Vec_CFr): CSize {.importc: "ffi_vec_cfr_len", +proc ffi_vec_fr_len*(v: ptr Vec_Fr): CSize {.importc: "ffi_vec_fr_len", cdecl, dynlib: RLN_LIB.} -proc ffi_vec_cfr_get*(v: ptr Vec_CFr, i: CSize): ptr CFr {.importc: "ffi_vec_cfr_get", +proc ffi_vec_fr_get*(v: ptr Vec_Fr, i: CSize): ptr Fr {.importc: "ffi_vec_fr_get", cdecl, dynlib: RLN_LIB.} -proc ffi_vec_cfr_to_bytes_le*(v: ptr Vec_CFr): VecU8Result {.importc: "ffi_vec_cfr_to_bytes_le", +proc ffi_vec_fr_to_bytes_le*(v: ptr Vec_Fr): VecU8Result {.importc: "ffi_vec_fr_to_bytes_le", cdecl, dynlib: RLN_LIB.} -proc ffi_vec_cfr_to_bytes_be*(v: ptr Vec_CFr): VecU8Result {.importc: "ffi_vec_cfr_to_bytes_be", +proc ffi_vec_fr_to_bytes_be*(v: ptr Vec_Fr): VecU8Result {.importc: "ffi_vec_fr_to_bytes_be", cdecl, dynlib: RLN_LIB.} -proc ffi_bytes_le_to_vec_cfr*(bytes: ptr Vec_uint8): VecCFrResult {.importc: "ffi_bytes_le_to_vec_cfr", +proc ffi_bytes_le_to_vec_fr*(bytes: ptr Vec_uint8): VecFrResult {.importc: "ffi_bytes_le_to_vec_fr", cdecl, dynlib: RLN_LIB.} -proc ffi_bytes_be_to_vec_cfr*(bytes: ptr Vec_uint8): VecCFrResult {.importc: "ffi_bytes_be_to_vec_cfr", +proc ffi_bytes_be_to_vec_fr*(bytes: ptr Vec_uint8): VecFrResult {.importc: "ffi_bytes_be_to_vec_fr", cdecl, dynlib: RLN_LIB.} -proc ffi_vec_cfr_debug*(v: ptr Vec_CFr): Vec_uint8 {.importc: "ffi_vec_cfr_debug", +proc ffi_vec_fr_debug*(v: ptr Vec_Fr): Vec_uint8 {.importc: "ffi_vec_fr_debug", cdecl, dynlib: RLN_LIB.} -proc ffi_vec_cfr_free*(v: Vec_CFr) {.importc: "ffi_vec_cfr_free", cdecl, +proc ffi_vec_fr_free*(v: Vec_Fr) {.importc: "ffi_vec_fr_free", cdecl, dynlib: RLN_LIB.} # Vec functions @@ -159,24 +182,75 @@ proc ffi_vec_u8_free*(v: Vec_uint8) {.importc: "ffi_vec_u8_free", cdecl, dynlib: RLN_LIB.} # Hashing functions -proc ffi_hash_to_field_le*(input: ptr Vec_uint8): ptr CFr {.importc: "ffi_hash_to_field_le", +proc ffi_hash_to_field_le*(input: ptr Vec_uint8): ptr Fr {.importc: "ffi_hash_to_field_le", cdecl, dynlib: RLN_LIB.} -proc ffi_hash_to_field_be*(input: ptr Vec_uint8): ptr CFr {.importc: "ffi_hash_to_field_be", +proc ffi_hash_to_field_be*(input: ptr Vec_uint8): ptr Fr {.importc: "ffi_hash_to_field_be", cdecl, dynlib: RLN_LIB.} -proc ffi_poseidon_hash_pair*(a: ptr CFr, - b: ptr CFr): ptr CFr {.importc: "ffi_poseidon_hash_pair", cdecl, +proc ffi_poseidon_hash_pair*(a: ptr Fr, + b: ptr Fr): ptr Fr {.importc: "ffi_poseidon_hash_pair", cdecl, dynlib: RLN_LIB.} -# Identity functions -proc ffi_key_gen*(): Vec_CFr {.importc: "ffi_key_gen", cdecl, dynlib: RLN_LIB.} -proc ffi_seeded_key_gen*(seed: ptr Vec_uint8): Vec_CFr {.importc: "ffi_seeded_key_gen", - cdecl, dynlib: RLN_LIB.} - -# ExtendedIdentity functions -proc ffi_extended_key_gen*(): Vec_CFr {.importc: "ffi_extended_key_gen", cdecl, - dynlib: RLN_LIB.} -proc ffi_seeded_extended_key_gen*(seed: ptr Vec_uint8): Vec_CFr {.importc: "ffi_seeded_extended_key_gen", - cdecl, dynlib: RLN_LIB.} +# SecretFr functions +proc ffi_secret_fr_debug*(secret: ptr SecretFr): Vec_uint8 {.importc: "ffi_secret_fr_debug", + cdecl, dynlib: RLN_LIB.} +proc ffi_secret_fr_free*(secret: ptr SecretFr) {.importc: "ffi_secret_fr_free", + cdecl, dynlib: RLN_LIB.} + +# Identity key functions +proc ffi_identity_keys_generate*(): ptr IdentityKeys {.importc: "ffi_identity_keys_generate", + cdecl, dynlib: RLN_LIB.} +proc ffi_identity_keys_generate_seeded*( + seed: ptr Vec_uint8): ptr IdentityKeys {.importc: "ffi_identity_keys_generate_seeded", + cdecl, dynlib: RLN_LIB.} +proc ffi_identity_keys_get_secret*(identity: ptr IdentityKeys): ptr SecretFr {.importc: "ffi_identity_keys_get_secret", + cdecl, dynlib: RLN_LIB.} +proc ffi_identity_keys_get_commitment*(identity: ptr IdentityKeys): ptr Fr {.importc: "ffi_identity_keys_get_commitment", + cdecl, dynlib: RLN_LIB.} +proc ffi_identity_keys_to_bytes_le*(identity: ptr IdentityKeys): VecU8Result {.importc: "ffi_identity_keys_to_bytes_le", + cdecl, dynlib: RLN_LIB.} +proc ffi_identity_keys_to_bytes_be*(identity: ptr IdentityKeys): VecU8Result {.importc: "ffi_identity_keys_to_bytes_be", + cdecl, dynlib: RLN_LIB.} +proc ffi_identity_keys_from_bytes_le*(bytes: ptr Vec_uint8): IdentityKeysResult {.importc: "ffi_identity_keys_from_bytes_le", + cdecl, dynlib: RLN_LIB.} +proc ffi_identity_keys_from_bytes_be*(bytes: ptr Vec_uint8): IdentityKeysResult {.importc: "ffi_identity_keys_from_bytes_be", + cdecl, dynlib: RLN_LIB.} +proc ffi_identity_keys_free*(identity: ptr IdentityKeys) {.importc: "ffi_identity_keys_free", + cdecl, dynlib: RLN_LIB.} + +# Extended identity key functions +proc ffi_extended_identity_keys_generate*( + ): ptr ExtendedIdentityKeys {.importc: "ffi_extended_identity_keys_generate", + +cdecl, dynlib: RLN_LIB.} +proc ffi_extended_identity_keys_generate_seeded*( + seed: ptr Vec_uint8): ptr ExtendedIdentityKeys {.importc: "ffi_extended_identity_keys_generate_seeded", + cdecl, dynlib: RLN_LIB.} +proc ffi_extended_identity_keys_get_trapdoor*( + identity: ptr ExtendedIdentityKeys): ptr SecretFr {.importc: "ffi_extended_identity_keys_get_trapdoor", + cdecl, dynlib: RLN_LIB.} +proc ffi_extended_identity_keys_get_nullifier*( + identity: ptr ExtendedIdentityKeys): ptr SecretFr {.importc: "ffi_extended_identity_keys_get_nullifier", + cdecl, dynlib: RLN_LIB.} +proc ffi_extended_identity_keys_get_secret*( + identity: ptr ExtendedIdentityKeys): ptr SecretFr {.importc: "ffi_extended_identity_keys_get_secret", + cdecl, dynlib: RLN_LIB.} +proc ffi_extended_identity_keys_get_commitment*( + identity: ptr ExtendedIdentityKeys): ptr Fr {.importc: "ffi_extended_identity_keys_get_commitment", + cdecl, dynlib: RLN_LIB.} +proc ffi_extended_identity_keys_to_bytes_le*( + identity: ptr ExtendedIdentityKeys): VecU8Result {.importc: "ffi_extended_identity_keys_to_bytes_le", + cdecl, dynlib: RLN_LIB.} +proc ffi_extended_identity_keys_to_bytes_be*( + identity: ptr ExtendedIdentityKeys): VecU8Result {.importc: "ffi_extended_identity_keys_to_bytes_be", + cdecl, dynlib: RLN_LIB.} +proc ffi_extended_identity_keys_from_bytes_le*( + bytes: ptr Vec_uint8): ExtendedIdentityKeysResult {.importc: "ffi_extended_identity_keys_from_bytes_le", + cdecl, dynlib: RLN_LIB.} +proc ffi_extended_identity_keys_from_bytes_be*( + bytes: ptr Vec_uint8): ExtendedIdentityKeysResult {.importc: "ffi_extended_identity_keys_from_bytes_be", + cdecl, dynlib: RLN_LIB.} +proc ffi_extended_identity_keys_free*(identity: ptr ExtendedIdentityKeys) {.importc: "ffi_extended_identity_keys_free", + cdecl, dynlib: RLN_LIB.} # CString functions proc ffi_c_string_free*(s: Vec_uint8) {.importc: "ffi_c_string_free", cdecl, @@ -218,12 +292,12 @@ proc ffi_rln_verify*(rln: ptr ptr RLN, cdecl, dynlib: RLN_LIB.} proc ffi_rln_verify_with_signal*(rln: ptr ptr RLN, proof: ptr ptr Proof, - x: ptr CFr): CBoolResult {.importc: "ffi_rln_verify_with_signal", + x: ptr Fr): CBoolResult {.importc: "ffi_rln_verify_with_signal", cdecl, dynlib: RLN_LIB.} proc ffi_rln_verify_with_roots*(rln: ptr ptr RLN, proof: ptr ptr Proof, - roots: ptr Vec_CFr, - x: ptr CFr): CBoolResult {.importc: "ffi_rln_verify_with_roots", + roots: ptr Vec_Fr, + x: ptr Fr): CBoolResult {.importc: "ffi_rln_verify_with_roots", cdecl, dynlib: RLN_LIB.} proc ffi_rln_generate_partial_proof*(rln: ptr ptr RLN, witness: ptr ptr PartialWitness): PartialProofResult {.importc: "ffi_rln_generate_partial_proof", @@ -236,39 +310,39 @@ proc ffi_rln_free*(rln: ptr RLN) {.importc: "ffi_rln_free", cdecl, dynlib: RLN_LIB.} # RLNWitnessInput functions -proc ffi_rln_witness_input_new_single*(identity_secret: ptr CFr, - user_message_limit: ptr CFr, message_id: ptr CFr, - path_elements: ptr Vec_CFr, identity_path_index: ptr Vec_uint8, x: ptr CFr, - external_nullifier: ptr CFr): WitnessResult {.importc: "ffi_rln_witness_input_new_single", - cdecl, dynlib: RLN_LIB.} -proc ffi_rln_witness_input_new_multi*(identity_secret: ptr CFr, - user_message_limit: ptr CFr, message_ids: ptr Vec_CFr, - path_elements: ptr Vec_CFr, identity_path_index: ptr Vec_uint8, x: ptr CFr, - external_nullifier: ptr CFr, +proc ffi_rln_witness_input_new_single*(identity_secret: ptr SecretFr, + user_message_limit: ptr Fr, message_id: ptr Fr, + path_elements: ptr Vec_Fr, identity_path_index: ptr Vec_uint8, x: ptr Fr, + external_nullifier: ptr Fr): WitnessResult {.importc: "ffi_rln_witness_input_new_single", + cdecl, dynlib: RLN_LIB.} +proc ffi_rln_witness_input_new_multi*(identity_secret: ptr SecretFr, + user_message_limit: ptr Fr, message_ids: ptr Vec_Fr, + path_elements: ptr Vec_Fr, identity_path_index: ptr Vec_uint8, x: ptr Fr, + external_nullifier: ptr Fr, selector_used: ptr Vec_bool): WitnessResult {.importc: "ffi_rln_witness_input_new_multi", cdecl, dynlib: RLN_LIB.} proc ffi_rln_witness_input_get_identity_secret*( - w: ptr ptr Witness): ptr CFr {.importc: "ffi_rln_witness_input_get_identity_secret", + w: ptr ptr Witness): ptr SecretFr {.importc: "ffi_rln_witness_input_get_identity_secret", cdecl, dynlib: RLN_LIB.} proc ffi_rln_witness_input_get_user_message_limit*( - w: ptr ptr Witness): ptr CFr {.importc: "ffi_rln_witness_input_get_user_message_limit", + w: ptr ptr Witness): ptr Fr {.importc: "ffi_rln_witness_input_get_user_message_limit", cdecl, dynlib: RLN_LIB.} proc ffi_rln_witness_input_get_message_id*( - w: ptr ptr Witness): CFrResult {.importc: "ffi_rln_witness_input_get_message_id", + w: ptr ptr Witness): FrResult {.importc: "ffi_rln_witness_input_get_message_id", cdecl, dynlib: RLN_LIB.} proc ffi_rln_witness_input_get_message_ids*( - w: ptr ptr Witness): VecCFrResult {.importc: "ffi_rln_witness_input_get_message_ids", + w: ptr ptr Witness): VecFrResult {.importc: "ffi_rln_witness_input_get_message_ids", cdecl, dynlib: RLN_LIB.} proc ffi_rln_witness_input_get_path_elements*( - w: ptr ptr Witness): Vec_CFr {.importc: "ffi_rln_witness_input_get_path_elements", + w: ptr ptr Witness): Vec_Fr {.importc: "ffi_rln_witness_input_get_path_elements", cdecl, dynlib: RLN_LIB.} proc ffi_rln_witness_input_get_identity_path_index*( w: ptr ptr Witness): Vec_uint8 {.importc: "ffi_rln_witness_input_get_identity_path_index", cdecl, dynlib: RLN_LIB.} -proc ffi_rln_witness_input_get_x*(w: ptr ptr Witness): ptr CFr {.importc: "ffi_rln_witness_input_get_x", +proc ffi_rln_witness_input_get_x*(w: ptr ptr Witness): ptr Fr {.importc: "ffi_rln_witness_input_get_x", cdecl, dynlib: RLN_LIB.} proc ffi_rln_witness_input_get_external_nullifier*( - w: ptr ptr Witness): ptr CFr {.importc: "ffi_rln_witness_input_get_external_nullifier", + w: ptr ptr Witness): ptr Fr {.importc: "ffi_rln_witness_input_get_external_nullifier", cdecl, dynlib: RLN_LIB.} proc ffi_rln_witness_input_get_selector_used*( w: ptr ptr Witness): VecBoolResult {.importc: "ffi_rln_witness_input_get_selector_used", @@ -285,18 +359,18 @@ proc ffi_rln_witness_input_free*(w: ptr Witness) {.importc: "ffi_rln_witness_inp cdecl, dynlib: RLN_LIB.} # RLNPartialWitnessInput functions -proc ffi_rln_partial_witness_input_new*(identity_secret: ptr CFr, - user_message_limit: ptr CFr, path_elements: ptr Vec_CFr, +proc ffi_rln_partial_witness_input_new*(identity_secret: ptr SecretFr, + user_message_limit: ptr Fr, path_elements: ptr Vec_Fr, identity_path_index: ptr Vec_uint8): PartialWitnessResult {.importc: "ffi_rln_partial_witness_input_new", cdecl, dynlib: RLN_LIB.} proc ffi_rln_partial_witness_input_get_identity_secret*( - w: ptr ptr PartialWitness): ptr CFr {.importc: "ffi_rln_partial_witness_input_get_identity_secret", + w: ptr ptr PartialWitness): ptr SecretFr {.importc: "ffi_rln_partial_witness_input_get_identity_secret", cdecl, dynlib: RLN_LIB.} proc ffi_rln_partial_witness_input_get_user_message_limit*( - w: ptr ptr PartialWitness): ptr CFr {.importc: "ffi_rln_partial_witness_input_get_user_message_limit", + w: ptr ptr PartialWitness): ptr Fr {.importc: "ffi_rln_partial_witness_input_get_user_message_limit", cdecl, dynlib: RLN_LIB.} proc ffi_rln_partial_witness_input_get_path_elements*( - w: ptr ptr PartialWitness): Vec_CFr {.importc: "ffi_rln_partial_witness_input_get_path_elements", + w: ptr ptr PartialWitness): Vec_Fr {.importc: "ffi_rln_partial_witness_input_get_path_elements", cdecl, dynlib: RLN_LIB.} proc ffi_rln_partial_witness_input_get_identity_path_index*( w: ptr ptr PartialWitness): Vec_uint8 {.importc: "ffi_rln_partial_witness_input_get_identity_path_index", @@ -345,25 +419,25 @@ proc ffi_rln_partial_proof_free*(p: ptr PartialProof) {.importc: "ffi_rln_partia cdecl, dynlib: RLN_LIB.} # RLNProofValues functions -proc ffi_rln_proof_values_get_root*(pv: ptr ptr ProofValues): ptr CFr {.importc: "ffi_rln_proof_values_get_root", +proc ffi_rln_proof_values_get_root*(pv: ptr ptr ProofValues): ptr Fr {.importc: "ffi_rln_proof_values_get_root", cdecl, dynlib: RLN_LIB.} -proc ffi_rln_proof_values_get_x*(pv: ptr ptr ProofValues): ptr CFr {.importc: "ffi_rln_proof_values_get_x", +proc ffi_rln_proof_values_get_x*(pv: ptr ptr ProofValues): ptr Fr {.importc: "ffi_rln_proof_values_get_x", cdecl, dynlib: RLN_LIB.} proc ffi_rln_proof_values_get_external_nullifier*( - pv: ptr ptr ProofValues): ptr CFr {.importc: "ffi_rln_proof_values_get_external_nullifier", + pv: ptr ptr ProofValues): ptr Fr {.importc: "ffi_rln_proof_values_get_external_nullifier", cdecl, dynlib: RLN_LIB.} -proc ffi_rln_proof_values_get_y*(pv: ptr ptr ProofValues): CFrResult {.importc: "ffi_rln_proof_values_get_y", +proc ffi_rln_proof_values_get_y*(pv: ptr ptr ProofValues): FrResult {.importc: "ffi_rln_proof_values_get_y", cdecl, dynlib: RLN_LIB.} proc ffi_rln_proof_values_get_nullifier*( - pv: ptr ptr ProofValues): CFrResult {.importc: "ffi_rln_proof_values_get_nullifier", + pv: ptr ptr ProofValues): FrResult {.importc: "ffi_rln_proof_values_get_nullifier", cdecl, dynlib: RLN_LIB.} proc ffi_rln_proof_values_get_selector_used*( pv: ptr ptr ProofValues): VecBoolResult {.importc: "ffi_rln_proof_values_get_selector_used", cdecl, dynlib: RLN_LIB.} -proc ffi_rln_proof_values_get_ys*(pv: ptr ptr ProofValues): VecCFrResult {.importc: "ffi_rln_proof_values_get_ys", +proc ffi_rln_proof_values_get_ys*(pv: ptr ptr ProofValues): VecFrResult {.importc: "ffi_rln_proof_values_get_ys", cdecl, dynlib: RLN_LIB.} proc ffi_rln_proof_values_get_nullifiers*( - pv: ptr ptr ProofValues): VecCFrResult {.importc: "ffi_rln_proof_values_get_nullifiers", + pv: ptr ptr ProofValues): VecFrResult {.importc: "ffi_rln_proof_values_get_nullifiers", cdecl, dynlib: RLN_LIB.} proc ffi_rln_proof_values_to_bytes_le*( pv: ptr ptr ProofValues): VecU8Result {.importc: "ffi_rln_proof_values_to_bytes_le", @@ -381,12 +455,12 @@ proc ffi_rln_proof_values_free*(pv: ptr ProofValues) {.importc: "ffi_rln_proof_v cdecl, dynlib: RLN_LIB.} # Identity secret recovery -proc ffi_rln_compute_id_secret*(share1_x: ptr CFr, share1_y: ptr CFr, - share2_x: ptr CFr, - share2_y: ptr CFr): CFrResult {.importc: "ffi_rln_compute_id_secret", +proc ffi_rln_compute_id_secret*(share1_x: ptr Fr, share1_y: ptr Fr, + share2_x: ptr Fr, + share2_y: ptr Fr): SecretFrResult {.importc: "ffi_rln_compute_id_secret", cdecl, dynlib: RLN_LIB.} proc ffi_rln_recover_id_secret*(pv1: ptr ptr ProofValues, - pv2: ptr ptr ProofValues): CFrResult {.importc: "ffi_rln_recover_id_secret", + pv2: ptr ptr ProofValues): SecretFrResult {.importc: "ffi_rln_recover_id_secret", cdecl, dynlib: RLN_LIB.} # Merkle tree operations (stateful mode) @@ -396,31 +470,31 @@ proc ffi_rln_tree_depth*(rln: ptr ptr RLN): CSize {.importc: "ffi_rln_tree_depth cdecl, dynlib: RLN_LIB.} proc ffi_rln_leaves_set*(rln: ptr ptr RLN): CSize {.importc: "ffi_rln_leaves_set", cdecl, dynlib: RLN_LIB.} -proc ffi_rln_get_root*(rln: ptr ptr RLN): ptr CFr {.importc: "ffi_rln_get_root", +proc ffi_rln_get_root*(rln: ptr ptr RLN): ptr Fr {.importc: "ffi_rln_get_root", cdecl, dynlib: RLN_LIB.} proc ffi_rln_get_subtree_root*(rln: ptr ptr RLN, level: CSize, - index: CSize): CFrResult {.importc: "ffi_rln_get_subtree_root", cdecl, + index: CSize): FrResult {.importc: "ffi_rln_get_subtree_root", cdecl, dynlib: RLN_LIB.} proc ffi_rln_set_leaf*(rln: ptr ptr RLN, index: CSize, - leaf: ptr CFr): CBoolResult {.importc: "ffi_rln_set_leaf", cdecl, + leaf: ptr Fr): CBoolResult {.importc: "ffi_rln_set_leaf", cdecl, dynlib: RLN_LIB.} proc ffi_rln_set_leaves_from*(rln: ptr ptr RLN, index: CSize, - leaves: ptr Vec_CFr): CBoolResult {.importc: "ffi_rln_set_leaves_from", + leaves: ptr Vec_Fr): CBoolResult {.importc: "ffi_rln_set_leaves_from", cdecl, dynlib: RLN_LIB.} proc ffi_rln_init_tree_with_leaves*(rln: ptr ptr RLN, - leaves: ptr Vec_CFr): CBoolResult {.importc: "ffi_rln_init_tree_with_leaves", + leaves: ptr Vec_Fr): CBoolResult {.importc: "ffi_rln_init_tree_with_leaves", cdecl, dynlib: RLN_LIB.} proc ffi_rln_get_leaf*(rln: ptr ptr RLN, - index: CSize): CFrResult {.importc: "ffi_rln_get_leaf", cdecl, + index: CSize): FrResult {.importc: "ffi_rln_get_leaf", cdecl, dynlib: RLN_LIB.} proc ffi_rln_get_empty_leaves_indices*(rln: ptr ptr RLN): VecSizeResult {.importc: "ffi_rln_get_empty_leaves_indices", cdecl, dynlib: RLN_LIB.} proc ffi_rln_atomic_operation*(rln: ptr ptr RLN, index: CSize, - leaves: ptr Vec_CFr, + leaves: ptr Vec_Fr, indices: ptr Vec_size): CBoolResult {.importc: "ffi_rln_atomic_operation", cdecl, dynlib: RLN_LIB.} proc ffi_rln_set_next_leaf*(rln: ptr ptr RLN, - leaf: ptr CFr): CBoolResult {.importc: "ffi_rln_set_next_leaf", cdecl, + leaf: ptr Fr): CBoolResult {.importc: "ffi_rln_set_next_leaf", cdecl, dynlib: RLN_LIB.} proc ffi_rln_delete_leaf*(rln: ptr ptr RLN, index: CSize): CBoolResult {.importc: "ffi_rln_delete_leaf", cdecl, diff --git a/rln/ffi_nim_examples/stateless.nim b/rln/ffi_nim_examples/stateless.nim index 839ea829..8d8626ea 100644 --- a/rln/ffi_nim_examples/stateless.nim +++ b/rln/ffi_nim_examples/stateless.nim @@ -8,16 +8,16 @@ proc main() = var member = createMember() echo "\nComputing Merkle path for stateless mode" - let defaultLeaf = ffi_cfr_zero() - var defaultHashes: array[treeDepth - 1, ptr CFr] + let defaultLeaf = ffi_fr_zero() + var defaultHashes: array[treeDepth - 1, ptr Fr] defaultHashes[0] = ffi_poseidon_hash_pair(defaultLeaf, defaultLeaf) for i in 1 ..< treeDepth - 1: defaultHashes[i] = ffi_poseidon_hash_pair(defaultHashes[i - 1], defaultHashes[i - 1]) - var pathElements = ffi_vec_cfr_new(csize_t(treeDepth)) - ffi_vec_cfr_push(addr pathElements, defaultLeaf) + var pathElements = ffi_vec_fr_new(csize_t(treeDepth)) + ffi_vec_fr_push(addr pathElements, defaultLeaf) for i in 1 ..< treeDepth: - ffi_vec_cfr_push(addr pathElements, defaultHashes[i - 1]) + ffi_vec_fr_push(addr pathElements, defaultHashes[i - 1]) var pathIndexData: array[treeDepth, uint8] var pathIndex = Vec_uint8(dataPtr: addr pathIndexData[0], len: csize_t(treeDepth), cap: csize_t(treeDepth)) @@ -27,11 +27,11 @@ proc main() = var computedRoot = ffi_poseidon_hash_pair(member.rateCommitment, defaultLeaf) for i in 1 ..< treeDepth: let nextRoot = ffi_poseidon_hash_pair(computedRoot, defaultHashes[i - 1]) - ffi_cfr_free(computedRoot) + ffi_fr_free(computedRoot) computedRoot = nextRoot - printCfr("computed root", computedRoot) - var roots = ffi_vec_cfr_new(csize_t(1)) - ffi_vec_cfr_push(addr roots, computedRoot) + printFr("computed root", computedRoot) + var roots = ffi_vec_fr_new(csize_t(1)) + ffi_vec_fr_push(addr roots, computedRoot) let externalNullifier = computeExternalNullifier() @@ -39,11 +39,11 @@ proc main() = var signal: array[32, uint8] = [1'u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] let x = hashSignal(signal) - printCfr("x", x) + printFr("x", x) echo "\nCreating message id" - let messageId = ffi_uint_to_cfr(0'u32) - printCfr("message id", messageId) + let messageId = ffi_uint_to_fr(0'u32) + printFr("message id", messageId) echo "\nCreating RLN witness" let witnessResult = ffi_rln_witness_input_new_single(member.identitySecret, @@ -72,25 +72,25 @@ proc main() = stderr.writeLine("Get y error: " & asString(yResult.err)) ffi_c_string_free(yResult.err) return - printCfr("y", yResult.ok) - ffi_cfr_free(yResult.ok) + printFr("y", yResult.ok) + ffi_fr_free(yResult.ok) let nullifierResult = ffi_rln_proof_values_get_nullifier(addr proofValues) if nullifierResult.ok.isNil: stderr.writeLine("Get nullifier error: " & asString(nullifierResult.err)) ffi_c_string_free(nullifierResult.err) return - printCfr("nullifier", nullifierResult.ok) - ffi_cfr_free(nullifierResult.ok) + printFr("nullifier", nullifierResult.ok) + ffi_fr_free(nullifierResult.ok) let proofValuesRoot = ffi_rln_proof_values_get_root(addr proofValues) - printCfr("root", proofValuesRoot) - ffi_cfr_free(proofValuesRoot) + printFr("root", proofValuesRoot) + ffi_fr_free(proofValuesRoot) let proofValuesX = ffi_rln_proof_values_get_x(addr proofValues) - printCfr("x", proofValuesX) - ffi_cfr_free(proofValuesX) + printFr("x", proofValuesX) + ffi_fr_free(proofValuesX) let proofValuesExternalNullifier = ffi_rln_proof_values_get_external_nullifier(addr proofValues) - printCfr("external nullifier", proofValuesExternalNullifier) - ffi_cfr_free(proofValuesExternalNullifier) + printFr("external nullifier", proofValuesExternalNullifier) + ffi_fr_free(proofValuesExternalNullifier) echo "\nVerifying proof" let verifyResult = ffi_rln_verify_with_roots(addr rlnInstance, @@ -108,15 +108,15 @@ proc main() = ffi_rln_proof_values_free(proofValues) ffi_rln_proof_free(rlnProof) ffi_rln_witness_input_free(witness) - ffi_cfr_free(messageId) - ffi_cfr_free(x) - ffi_cfr_free(externalNullifier) - ffi_vec_cfr_free(roots) - ffi_cfr_free(computedRoot) - ffi_vec_cfr_free(pathElements) + ffi_fr_free(messageId) + ffi_fr_free(x) + ffi_fr_free(externalNullifier) + ffi_vec_fr_free(roots) + ffi_fr_free(computedRoot) + ffi_vec_fr_free(pathElements) for i in 0 ..< treeDepth - 1: - ffi_cfr_free(defaultHashes[i]) - ffi_cfr_free(defaultLeaf) + ffi_fr_free(defaultHashes[i]) + ffi_fr_free(defaultLeaf) memberFree(member) ffi_rln_free(rlnInstance) diff --git a/rln/ffi_nim_examples/type_serialization.nim b/rln/ffi_nim_examples/type_serialization.nim index 53ce5156..c1788906 100644 --- a/rln/ffi_nim_examples/type_serialization.nim +++ b/rln/ffi_nim_examples/type_serialization.nim @@ -17,11 +17,11 @@ proc main() = var signal: array[32, uint8] = [1'u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] let x = hashSignal(signal) - printCfr("x", x) + printFr("x", x) echo "\nCreating message id" - let messageId = ffi_uint_to_cfr(0'u32) - printCfr("message id", messageId) + let messageId = ffi_uint_to_fr(0'u32) + printFr("message id", messageId) echo "\nCreating RLN witness" let witnessResult = createWitness(member, merkleProof, messageId, x, @@ -97,9 +97,9 @@ proc main() = ffi_rln_witness_input_free(deserWitness) ffi_vec_u8_free(serWitness) ffi_rln_witness_input_free(witness) - ffi_cfr_free(messageId) - ffi_cfr_free(x) - ffi_cfr_free(externalNullifier) + ffi_fr_free(messageId) + ffi_fr_free(x) + ffi_fr_free(externalNullifier) ffi_rln_merkle_proof_free(merkleProof) memberFree(member) ffi_rln_free(rlnInstance) diff --git a/rln/src/circuit/iden3calc.rs b/rln/src/circuit/iden3calc.rs index caea1902..c9506b9d 100644 --- a/rln/src/circuit/iden3calc.rs +++ b/rln/src/circuit/iden3calc.rs @@ -29,7 +29,7 @@ pub(crate) fn calc_witness)>>( value .iter() .map(|f_| match f_ { - FrOrSecret::IdSecret(s) => s.to_u256(), + FrOrSecret::SecretFr(s) => s.to_u256(), FrOrSecret::Fr(f) => fr_to_u256(f), }) .collect(), @@ -72,7 +72,7 @@ pub(crate) fn calc_witness_partial s.to_u256(), + FrOrSecret::SecretFr(s) => s.to_u256(), FrOrSecret::Fr(f) => fr_to_u256(f), }) }) diff --git a/rln/src/circuit/mod.rs b/rln/src/circuit/mod.rs index 682d25e6..094d44b0 100644 --- a/rln/src/circuit/mod.rs +++ b/rln/src/circuit/mod.rs @@ -6,7 +6,7 @@ pub(crate) mod qap; mod backend; mod graph; -mod id_secret; +mod secret_fr; mod types; mod zkey; @@ -15,8 +15,8 @@ pub use backend::ArkGroth16Backend; pub use graph::{default_graph_multi, default_graph_single}; pub use graph::{graph_from_raw, Graph}; pub(crate) use graph::{CalcWitness, CalcWitnessPartial}; -pub(crate) use id_secret::FrOrSecret; -pub use id_secret::IdSecret; +pub(crate) use secret_fr::FrOrSecret; +pub use secret_fr::SecretFr; pub use types::{ Curve, Fq, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective, PartialProof, Proof, ProvingKey, VerifyingKey, Zkey, COMPRESS_PROOF_SIZE, DEFAULT_MAX_OUT, DEFAULT_TREE_DEPTH, diff --git a/rln/src/circuit/id_secret.rs b/rln/src/circuit/secret_fr.rs similarity index 78% rename from rln/src/circuit/id_secret.rs rename to rln/src/circuit/secret_fr.rs index 4c6013ce..496af28a 100644 --- a/rln/src/circuit/id_secret.rs +++ b/rln/src/circuit/secret_fr.rs @@ -8,16 +8,13 @@ use zeroize::{Zeroize, ZeroizeOnDrop}; use super::Fr; -// TODO(PR12): consider renaming `IdSecret` to a general `SecretFr` wrapper so the extended keygen -// secrets (`identity_trapdoor` / `identity_nullifier`, today raw `Fr`) can be zeroize-protected too. - /// Secret field-element wrapper zeroized on drop. #[derive( Debug, Zeroize, ZeroizeOnDrop, Clone, PartialEq, CanonicalSerialize, CanonicalDeserialize, )] -pub struct IdSecret(Fr); +pub struct SecretFr(Fr); -impl IdSecret { +impl SecretFr { pub fn rand(rng: &mut R) -> Self { let mut fr = Fr::rand(rng); let res = Self::from(&mut fr); @@ -36,15 +33,15 @@ impl IdSecret { } } -impl From<&mut Fr> for IdSecret { +impl From<&mut Fr> for SecretFr { fn from(value: &mut Fr) -> Self { let id_secret = Self(*value); - value.zeroize(); // clear the caller-owned source Fr after the secret moved into IdSecret + value.zeroize(); // clear the caller-owned source Fr after the secret moved into SecretFr id_secret } } -impl Deref for IdSecret { +impl Deref for SecretFr { type Target = Fr; /// Deref to &Fr @@ -58,7 +55,7 @@ impl Deref for IdSecret { #[derive(Debug, Clone, Zeroize, ZeroizeOnDrop)] pub(crate) enum FrOrSecret { - IdSecret(IdSecret), + SecretFr(SecretFr), Fr(Fr), } @@ -68,9 +65,9 @@ impl From for FrOrSecret { } } -impl From for FrOrSecret { - fn from(value: IdSecret) -> Self { - FrOrSecret::IdSecret(value) +impl From for FrOrSecret { + fn from(value: SecretFr) -> Self { + FrOrSecret::SecretFr(value) } } @@ -81,7 +78,7 @@ mod test { #[test] fn test_id_secret_from_fr_zeroizes_source() { let mut fr = Fr::from(42); - let id_secret = IdSecret::from(&mut fr); + let id_secret = SecretFr::from(&mut fr); assert_ne!(fr, Fr::from(42)); assert_eq!(*id_secret, Fr::from(42)); diff --git a/rln/src/ffi/ffi_rln.rs b/rln/src/ffi/ffi_rln.rs index ccf12ad1..0f584b8b 100644 --- a/rln/src/ffi/ffi_rln.rs +++ b/rln/src/ffi/ffi_rln.rs @@ -12,7 +12,7 @@ use zerokit_utils::merkle_tree::{ FullMerkleTree, Hasher, OptimalMerkleTree, ZerokitMerkleProof, ZerokitMerkleTree, }; -use super::ffi_utils::{CBoolResult, CFr, CResult}; +use super::ffi_utils::{FFI_BoolResult, FFI_Fr, FFI_Result, FFI_SecretFr}; use crate::prelude::*; const MAX_CONFIG_SIZE: u64 = 1024 * 1024; @@ -382,16 +382,16 @@ pub fn ffi_rln_new_stateless_default() -> repr_c::Box { pub fn ffi_rln_new_stateless( zkey_data: &repr_c::Vec, graph_data: &repr_c::Vec, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match parse_zkey_and_graph(zkey_data, graph_data) { Ok((zkey, graph)) => { let rln = RLNBuilder::stateless().graph(graph).zkey(zkey).build(); - CResult { + FFI_Result { ok: Some(Box_::new(FFI_RLN(rln.into()))), err: None, } } - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.into()), }, @@ -399,17 +399,17 @@ pub fn ffi_rln_new_stateless( } #[ffi_export] -pub fn ffi_rln_new_with_full_merkle_tree_default() -> CResult, repr_c::String> -{ +pub fn ffi_rln_new_with_full_merkle_tree_default( +) -> FFI_Result, repr_c::String> { match FullMerkleTree::::default(DEFAULT_TREE_DEPTH) { Ok(full_merkle_tree) => { let rln = RLNBuilder::stateful().tree(full_merkle_tree).build(); - CResult { + FFI_Result { ok: Some(Box_::new(FFI_RLN(rln.into()))), err: None, } } - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -421,11 +421,11 @@ pub fn ffi_rln_new_with_full_merkle_tree( tree_depth: usize, zkey_data: &repr_c::Vec, graph_data: &repr_c::Vec, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { let (zkey, graph) = match parse_zkey_and_graph(zkey_data, graph_data) { Ok(parsed) => parsed, Err(err) => { - return CResult { + return FFI_Result { ok: None, err: Some(err.into()), } @@ -438,12 +438,12 @@ pub fn ffi_rln_new_with_full_merkle_tree( .graph(graph) .zkey(zkey) .build(); - CResult { + FFI_Result { ok: Some(Box_::new(FFI_RLN(rln.into()))), err: None, } } - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -452,16 +452,16 @@ pub fn ffi_rln_new_with_full_merkle_tree( #[ffi_export] pub fn ffi_rln_new_with_optimal_merkle_tree_default( -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match OptimalMerkleTree::::default(DEFAULT_TREE_DEPTH) { Ok(optimal_merkle_tree) => { let rln = RLNBuilder::stateful().tree(optimal_merkle_tree).build(); - CResult { + FFI_Result { ok: Some(Box_::new(FFI_RLN(rln.into()))), err: None, } } - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -473,11 +473,11 @@ pub fn ffi_rln_new_with_optimal_merkle_tree( tree_depth: usize, zkey_data: &repr_c::Vec, graph_data: &repr_c::Vec, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { let (zkey, graph) = match parse_zkey_and_graph(zkey_data, graph_data) { Ok(parsed) => parsed, Err(err) => { - return CResult { + return FFI_Result { ok: None, err: Some(err.into()), } @@ -490,12 +490,12 @@ pub fn ffi_rln_new_with_optimal_merkle_tree( .graph(graph) .zkey(zkey) .build(); - CResult { + FFI_Result { ok: Some(Box_::new(FFI_RLN(rln.into()))), err: None, } } - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -503,16 +503,16 @@ pub fn ffi_rln_new_with_optimal_merkle_tree( } #[ffi_export] -pub fn ffi_rln_new_with_pm_tree_default() -> CResult, repr_c::String> { +pub fn ffi_rln_new_with_pm_tree_default() -> FFI_Result, repr_c::String> { match PmTree::default(DEFAULT_TREE_DEPTH) { Ok(pm_tree) => { let rln = RLNBuilder::stateful().tree(pm_tree).build(); - CResult { + FFI_Result { ok: Some(Box_::new(FFI_RLN(rln.into()))), err: None, } } - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -525,11 +525,11 @@ pub fn ffi_rln_new_with_pm_tree( zkey_data: &repr_c::Vec, graph_data: &repr_c::Vec, config_path: char_p::Ref<'_>, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { let (zkey, graph) = match parse_zkey_and_graph(zkey_data, graph_data) { Ok(parsed) => parsed, Err(err) => { - return CResult { + return FFI_Result { ok: None, err: Some(err.into()), } @@ -556,16 +556,16 @@ pub fn ffi_rln_new_with_pm_tree( let pm_tree = if config_str.is_empty() { PmTree::default(tree_depth) } else { - let cfg = match PmTreeSledConfig::from_str(&config_str) { - Ok(c) => c, + let config = match PmTreeSledConfig::from_str(&config_str) { + Ok(config) => config, Err(err) => { - return CResult { + return FFI_Result { ok: None, err: Some(err.to_string().into()), } } }; - PmTree::new(tree_depth, PoseidonHash::default_leaf(), cfg) + PmTree::new(tree_depth, PoseidonHash::default_leaf(), config) }; match pm_tree { Ok(pm_tree) => { @@ -574,12 +574,12 @@ pub fn ffi_rln_new_with_pm_tree( .graph(graph) .zkey(zkey) .build(); - CResult { + FFI_Result { ok: Some(Box_::new(FFI_RLN(rln.into()))), err: None, } } - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -590,13 +590,13 @@ pub fn ffi_rln_new_with_pm_tree( pub fn ffi_rln_generate_proof( rln: &repr_c::Box, witness: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match rln.0.generate_proof(&witness.0) { - Ok((proof, values)) => CResult { + Ok((proof, values)) => FFI_Result { ok: Some(Box_::new(FFI_RLNProof(RLNProof::new(proof, values)))), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.into()), }, @@ -607,13 +607,13 @@ pub fn ffi_rln_generate_proof( pub fn ffi_rln_verify( rln: &repr_c::Box, rln_proof: &repr_c::Box, -) -> CBoolResult { +) -> FFI_BoolResult { match rln.0.verify(&rln_proof.0.proof, &rln_proof.0.values) { - Ok(verified) => CBoolResult { + Ok(verified) => FFI_BoolResult { ok: verified, err: None, }, - Err(err) => CBoolResult { + Err(err) => FFI_BoolResult { ok: false, err: Some(err.into()), }, @@ -624,17 +624,17 @@ pub fn ffi_rln_verify( pub fn ffi_rln_verify_with_signal( rln: &repr_c::Box, rln_proof: &repr_c::Box, - x: &CFr, -) -> CBoolResult { + x: &FFI_Fr, +) -> FFI_BoolResult { match rln .0 .verify_with_signal(&rln_proof.0.proof, &rln_proof.0.values, &x.0) { - Ok(verified) => CBoolResult { + Ok(verified) => FFI_BoolResult { ok: verified, err: None, }, - Err(err) => CBoolResult { + Err(err) => FFI_BoolResult { ok: false, err: Some(err.into()), }, @@ -645,19 +645,19 @@ pub fn ffi_rln_verify_with_signal( pub fn ffi_rln_verify_with_roots( rln: &repr_c::Box, rln_proof: &repr_c::Box, - roots: &repr_c::Vec, - x: &CFr, -) -> CBoolResult { - let roots_fr: Vec = roots.iter().map(|cfr| cfr.0).collect(); + roots: &repr_c::Vec, + x: &FFI_Fr, +) -> FFI_BoolResult { + let roots_fr: Vec = roots.iter().map(|fr| fr.0).collect(); match rln .0 .verify_with_roots(&rln_proof.0.proof, &rln_proof.0.values, &x.0, &roots_fr) { - Ok(verified) => CBoolResult { + Ok(verified) => FFI_BoolResult { ok: verified, err: None, }, - Err(err) => CBoolResult { + Err(err) => FFI_BoolResult { ok: false, err: Some(err.into()), }, @@ -668,13 +668,13 @@ pub fn ffi_rln_verify_with_roots( pub fn ffi_rln_generate_partial_proof( rln: &repr_c::Box, partial_witness: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match rln.0.generate_partial_proof(&partial_witness.0) { - Ok(pp) => CResult { + Ok(pp) => FFI_Result { ok: Some(Box_::new(FFI_RLNPartialProof(pp))), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.into()), }, @@ -686,13 +686,13 @@ pub fn ffi_rln_finish_proof( rln: &repr_c::Box, partial_proof: &repr_c::Box, witness: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match rln.0.finish_proof(&partial_proof.0, &witness.0) { - Ok((proof, values)) => CResult { + Ok((proof, values)) => FFI_Result { ok: Some(Box_::new(FFI_RLNProof(RLNProof::new(proof, values)))), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.into()), }, @@ -712,20 +712,19 @@ pub struct FFI_RLNWitnessInput(pub(crate) RLNWitnessInput); #[ffi_export] pub fn ffi_rln_witness_input_new_single( - identity_secret: &CFr, - user_message_limit: &CFr, - message_id: &CFr, - path_elements: &repr_c::Vec, + identity_secret: &FFI_SecretFr, + user_message_limit: &FFI_Fr, + message_id: &FFI_Fr, + path_elements: &repr_c::Vec, identity_path_index: &repr_c::Vec, - x: &CFr, - external_nullifier: &CFr, -) -> CResult, repr_c::String> { - let mut identity_secret_fr = identity_secret.0; - let path_elements: Vec = path_elements.iter().map(|cfr| cfr.0).collect(); + x: &FFI_Fr, + external_nullifier: &FFI_Fr, +) -> FFI_Result, repr_c::String> { + let path_elements: Vec = path_elements.iter().map(|fr| fr.0).collect(); let identity_path_index: Vec = identity_path_index.iter().copied().collect(); match RLNWitnessInput::new_single() - .identity_secret(IdSecret::from(&mut identity_secret_fr)) + .identity_secret(identity_secret.0.clone()) .user_message_limit(user_message_limit.0) .path_elements(path_elements) .identity_path_index(identity_path_index) @@ -734,11 +733,11 @@ pub fn ffi_rln_witness_input_new_single( .message_id(message_id.0) .build() { - Ok(w) => CResult { + Ok(w) => FFI_Result { ok: Some(Box_::new(FFI_RLNWitnessInput(w))), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -747,23 +746,22 @@ pub fn ffi_rln_witness_input_new_single( #[ffi_export] pub fn ffi_rln_witness_input_new_multi( - identity_secret: &CFr, - user_message_limit: &CFr, - message_ids: &repr_c::Vec, - path_elements: &repr_c::Vec, + identity_secret: &FFI_SecretFr, + user_message_limit: &FFI_Fr, + message_ids: &repr_c::Vec, + path_elements: &repr_c::Vec, identity_path_index: &repr_c::Vec, - x: &CFr, - external_nullifier: &CFr, + x: &FFI_Fr, + external_nullifier: &FFI_Fr, selector_used: &repr_c::Vec, -) -> CResult, repr_c::String> { - let mut identity_secret_fr = identity_secret.0; - let path_elements: Vec = path_elements.iter().map(|cfr| cfr.0).collect(); +) -> FFI_Result, repr_c::String> { + let path_elements: Vec = path_elements.iter().map(|fr| fr.0).collect(); let identity_path_index: Vec = identity_path_index.iter().copied().collect(); - let message_ids: Vec = message_ids.iter().map(|cfr| cfr.0).collect(); + let message_ids: Vec = message_ids.iter().map(|fr| fr.0).collect(); let selector_used: Vec = selector_used.iter().copied().collect(); match RLNWitnessInput::new_multi() - .identity_secret(IdSecret::from(&mut identity_secret_fr)) + .identity_secret(identity_secret.0.clone()) .user_message_limit(user_message_limit.0) .path_elements(path_elements) .identity_path_index(identity_path_index) @@ -773,11 +771,11 @@ pub fn ffi_rln_witness_input_new_multi( .selector_used(selector_used) .build() { - Ok(w) => CResult { + Ok(w) => FFI_Result { ok: Some(Box_::new(FFI_RLNWitnessInput(w))), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -787,27 +785,27 @@ pub fn ffi_rln_witness_input_new_multi( #[ffi_export] pub fn ffi_rln_witness_input_get_identity_secret( witness: &repr_c::Box, -) -> repr_c::Box { - CFr::from(**witness.0.identity_secret()).into() +) -> repr_c::Box { + Box_::new(FFI_SecretFr::from(witness.0.identity_secret().clone())) } #[ffi_export] pub fn ffi_rln_witness_input_get_user_message_limit( witness: &repr_c::Box, -) -> repr_c::Box { - CFr::from(witness.0.user_message_limit()).into() +) -> repr_c::Box { + FFI_Fr::from(witness.0.user_message_limit()).into() } #[ffi_export] pub fn ffi_rln_witness_input_get_message_id( witness: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match witness.0.message_id() { - Some(id) => CResult { - ok: Some(CFr::from(id).into()), + Some(id) => FFI_Result { + ok: Some(FFI_Fr::from(id).into()), err: None, }, - None => CResult { + None => FFI_Result { ok: None, err: Some("witness is Multi; use get_message_ids".into()), }, @@ -817,18 +815,18 @@ pub fn ffi_rln_witness_input_get_message_id( #[ffi_export] pub fn ffi_rln_witness_input_get_message_ids( witness: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match witness.0.message_ids() { - Some(ids) => CResult { + Some(ids) => FFI_Result { ok: Some( ids.iter() - .map(|fr| CFr::from(*fr)) + .map(|fr| FFI_Fr::from(*fr)) .collect::>() .into(), ), err: None, }, - None => CResult { + None => FFI_Result { ok: None, err: Some("witness is Single; use get_message_id".into()), }, @@ -838,12 +836,12 @@ pub fn ffi_rln_witness_input_get_message_ids( #[ffi_export] pub fn ffi_rln_witness_input_get_path_elements( witness: &repr_c::Box, -) -> repr_c::Vec { +) -> repr_c::Vec { witness .0 .path_elements() .iter() - .map(|fr| CFr::from(*fr)) + .map(|fr| FFI_Fr::from(*fr)) .collect::>() .into() } @@ -856,27 +854,29 @@ pub fn ffi_rln_witness_input_get_identity_path_index( } #[ffi_export] -pub fn ffi_rln_witness_input_get_x(witness: &repr_c::Box) -> repr_c::Box { - CFr::from(witness.0.x()).into() +pub fn ffi_rln_witness_input_get_x( + witness: &repr_c::Box, +) -> repr_c::Box { + FFI_Fr::from(witness.0.x()).into() } #[ffi_export] pub fn ffi_rln_witness_input_get_external_nullifier( witness: &repr_c::Box, -) -> repr_c::Box { - CFr::from(witness.0.external_nullifier()).into() +) -> repr_c::Box { + FFI_Fr::from(witness.0.external_nullifier()).into() } #[ffi_export] pub fn ffi_rln_witness_input_get_selector_used( witness: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match witness.0.selector_used() { - Some(s) => CResult { + Some(s) => FFI_Result { ok: Some(s.to_vec().into()), err: None, }, - None => CResult { + None => FFI_Result { ok: None, err: Some("witness is Single; selector_used is Multi-only".into()), }, @@ -886,14 +886,14 @@ pub fn ffi_rln_witness_input_get_selector_used( #[ffi_export] pub fn ffi_rln_witness_to_bytes_le( witness: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { let mut bytes = Vec::new(); match witness.0.serialize_compressed(&mut bytes) { - Ok(()) => CResult { + Ok(()) => FFI_Result { ok: Some(bytes.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -903,14 +903,14 @@ pub fn ffi_rln_witness_to_bytes_le( #[ffi_export] pub fn ffi_rln_witness_to_bytes_be( witness: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { let mut bytes = Vec::new(); match CanonicalSerializeBE::serialize(&witness.0, &mut bytes) { - Ok(()) => CResult { + Ok(()) => FFI_Result { ok: Some(bytes.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -920,13 +920,13 @@ pub fn ffi_rln_witness_to_bytes_be( #[ffi_export] pub fn ffi_bytes_le_to_rln_witness( bytes: &repr_c::Vec, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match RLNWitnessInput::deserialize_compressed(&bytes[..]) { - Ok(w) => CResult { + Ok(w) => FFI_Result { ok: Some(Box_::new(FFI_RLNWitnessInput(w))), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -936,13 +936,13 @@ pub fn ffi_bytes_le_to_rln_witness( #[ffi_export] pub fn ffi_bytes_be_to_rln_witness( bytes: &repr_c::Vec, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match ::deserialize(&bytes[..]) { - Ok(w) => CResult { + Ok(w) => FFI_Result { ok: Some(Box_::new(FFI_RLNWitnessInput(w))), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -962,26 +962,25 @@ pub struct FFI_RLNPartialWitnessInput(pub(crate) RLNPartialWitnessInput); #[ffi_export] pub fn ffi_rln_partial_witness_input_new( - identity_secret: &CFr, - user_message_limit: &CFr, - path_elements: &repr_c::Vec, + identity_secret: &FFI_SecretFr, + user_message_limit: &FFI_Fr, + path_elements: &repr_c::Vec, identity_path_index: &repr_c::Vec, -) -> CResult, repr_c::String> { - let mut identity_secret_fr = identity_secret.0; - let path_elements: Vec = path_elements.iter().map(|cfr| cfr.0).collect(); +) -> FFI_Result, repr_c::String> { + let path_elements: Vec = path_elements.iter().map(|fr| fr.0).collect(); let identity_path_index: Vec = identity_path_index.iter().copied().collect(); match RLNPartialWitnessInput::new() - .identity_secret(IdSecret::from(&mut identity_secret_fr)) + .identity_secret(identity_secret.0.clone()) .user_message_limit(user_message_limit.0) .path_elements(path_elements) .identity_path_index(identity_path_index) .build() { - Ok(w) => CResult { + Ok(w) => FFI_Result { ok: Some(Box_::new(FFI_RLNPartialWitnessInput(w))), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -991,26 +990,26 @@ pub fn ffi_rln_partial_witness_input_new( #[ffi_export] pub fn ffi_rln_partial_witness_input_get_identity_secret( witness: &repr_c::Box, -) -> repr_c::Box { - CFr::from(*witness.0.identity_secret).into() +) -> repr_c::Box { + Box_::new(FFI_SecretFr::from(witness.0.identity_secret.clone())) } #[ffi_export] pub fn ffi_rln_partial_witness_input_get_user_message_limit( witness: &repr_c::Box, -) -> repr_c::Box { - CFr::from(witness.0.user_message_limit).into() +) -> repr_c::Box { + FFI_Fr::from(witness.0.user_message_limit).into() } #[ffi_export] pub fn ffi_rln_partial_witness_input_get_path_elements( witness: &repr_c::Box, -) -> repr_c::Vec { +) -> repr_c::Vec { witness .0 .path_elements .iter() - .map(|fr| CFr::from(*fr)) + .map(|fr| FFI_Fr::from(*fr)) .collect::>() .into() } @@ -1033,14 +1032,14 @@ pub fn ffi_rln_witness_to_partial_witness( #[ffi_export] pub fn ffi_rln_partial_witness_to_bytes_le( witness: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { let mut bytes = Vec::new(); match witness.0.serialize_compressed(&mut bytes) { - Ok(()) => CResult { + Ok(()) => FFI_Result { ok: Some(bytes.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -1050,14 +1049,14 @@ pub fn ffi_rln_partial_witness_to_bytes_le( #[ffi_export] pub fn ffi_rln_partial_witness_to_bytes_be( witness: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { let mut bytes = Vec::new(); match CanonicalSerializeBE::serialize(&witness.0, &mut bytes) { - Ok(()) => CResult { + Ok(()) => FFI_Result { ok: Some(bytes.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -1067,13 +1066,13 @@ pub fn ffi_rln_partial_witness_to_bytes_be( #[ffi_export] pub fn ffi_bytes_le_to_rln_partial_witness( bytes: &repr_c::Vec, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match RLNPartialWitnessInput::deserialize_compressed(&bytes[..]) { - Ok(w) => CResult { + Ok(w) => FFI_Result { ok: Some(Box_::new(FFI_RLNPartialWitnessInput(w))), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -1083,13 +1082,13 @@ pub fn ffi_bytes_le_to_rln_partial_witness( #[ffi_export] pub fn ffi_bytes_be_to_rln_partial_witness( bytes: &repr_c::Vec, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match ::deserialize(&bytes[..]) { - Ok(w) => CResult { + Ok(w) => FFI_Result { ok: Some(Box_::new(FFI_RLNPartialWitnessInput(w))), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -1117,14 +1116,14 @@ pub fn ffi_rln_proof_get_values( #[ffi_export] pub fn ffi_rln_proof_to_bytes_le( rln_proof: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { let mut bytes = Vec::new(); match rln_proof.0.serialize_compressed(&mut bytes) { - Ok(()) => CResult { + Ok(()) => FFI_Result { ok: Some(bytes.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -1134,14 +1133,14 @@ pub fn ffi_rln_proof_to_bytes_le( #[ffi_export] pub fn ffi_rln_proof_to_bytes_mixed( rln_proof: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { let mut bytes = Vec::new(); match CanonicalSerializeMixed::serialize(&rln_proof.0, &mut bytes) { - Ok(()) => CResult { + Ok(()) => FFI_Result { ok: Some(bytes.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -1151,13 +1150,13 @@ pub fn ffi_rln_proof_to_bytes_mixed( #[ffi_export] pub fn ffi_bytes_le_to_rln_proof( bytes: &repr_c::Vec, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match RLNProof::deserialize_compressed(&bytes[..]) { - Ok(p) => CResult { + Ok(p) => FFI_Result { ok: Some(Box_::new(FFI_RLNProof(p))), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -1167,13 +1166,13 @@ pub fn ffi_bytes_le_to_rln_proof( #[ffi_export] pub fn ffi_bytes_mixed_to_rln_proof( bytes: &repr_c::Vec, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match ::deserialize(&bytes[..]) { - Ok(p) => CResult { + Ok(p) => FFI_Result { ok: Some(Box_::new(FFI_RLNProof(p))), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -1194,14 +1193,14 @@ pub struct FFI_RLNPartialProof(pub(crate) PartialProof); #[ffi_export] pub fn ffi_rln_partial_proof_to_bytes_le( partial_proof: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { let mut bytes = Vec::new(); match partial_proof.0.serialize_compressed(&mut bytes) { - Ok(()) => CResult { + Ok(()) => FFI_Result { ok: Some(bytes.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -1211,13 +1210,13 @@ pub fn ffi_rln_partial_proof_to_bytes_le( #[ffi_export] pub fn ffi_bytes_le_to_rln_partial_proof( bytes: &repr_c::Vec, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match PartialProof::deserialize_compressed(&bytes[..]) { - Ok(p) => CResult { + Ok(p) => FFI_Result { ok: Some(Box_::new(FFI_RLNPartialProof(p))), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -1236,32 +1235,32 @@ pub fn ffi_rln_partial_proof_free(partial_proof: repr_c::Box) -> repr_c::Box { - CFr::from(pv.0.root()).into() +pub fn ffi_rln_proof_values_get_root(pv: &repr_c::Box) -> repr_c::Box { + FFI_Fr::from(pv.0.root()).into() } #[ffi_export] -pub fn ffi_rln_proof_values_get_x(pv: &repr_c::Box) -> repr_c::Box { - CFr::from(pv.0.x()).into() +pub fn ffi_rln_proof_values_get_x(pv: &repr_c::Box) -> repr_c::Box { + FFI_Fr::from(pv.0.x()).into() } #[ffi_export] pub fn ffi_rln_proof_values_get_external_nullifier( pv: &repr_c::Box, -) -> repr_c::Box { - CFr::from(pv.0.external_nullifier()).into() +) -> repr_c::Box { + FFI_Fr::from(pv.0.external_nullifier()).into() } #[ffi_export] pub fn ffi_rln_proof_values_get_y( pv: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match pv.0.y() { - Some(y) => CResult { - ok: Some(CFr::from(y).into()), + Some(y) => FFI_Result { + ok: Some(FFI_Fr::from(y).into()), err: None, }, - None => CResult { + None => FFI_Result { ok: None, err: Some("values are Multi; use get_ys".into()), }, @@ -1271,13 +1270,13 @@ pub fn ffi_rln_proof_values_get_y( #[ffi_export] pub fn ffi_rln_proof_values_get_nullifier( pv: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match pv.0.nullifier() { - Some(n) => CResult { - ok: Some(CFr::from(n).into()), + Some(n) => FFI_Result { + ok: Some(FFI_Fr::from(n).into()), err: None, }, - None => CResult { + None => FFI_Result { ok: None, err: Some("values are Multi; use get_nullifiers".into()), }, @@ -1287,13 +1286,13 @@ pub fn ffi_rln_proof_values_get_nullifier( #[ffi_export] pub fn ffi_rln_proof_values_get_selector_used( pv: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match pv.0.selector_used() { - Some(s) => CResult { + Some(s) => FFI_Result { ok: Some(s.to_vec().into()), err: None, }, - None => CResult { + None => FFI_Result { ok: None, err: Some("values are Single; selector_used is Multi-only".into()), }, @@ -1303,18 +1302,18 @@ pub fn ffi_rln_proof_values_get_selector_used( #[ffi_export] pub fn ffi_rln_proof_values_get_ys( pv: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match pv.0.ys() { - Some(ys) => CResult { + Some(ys) => FFI_Result { ok: Some( ys.iter() - .map(|fr| CFr::from(*fr)) + .map(|fr| FFI_Fr::from(*fr)) .collect::>() .into(), ), err: None, }, - None => CResult { + None => FFI_Result { ok: None, err: Some("values are Single; use get_y".into()), }, @@ -1324,18 +1323,18 @@ pub fn ffi_rln_proof_values_get_ys( #[ffi_export] pub fn ffi_rln_proof_values_get_nullifiers( pv: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match pv.0.nullifiers() { - Some(ns) => CResult { + Some(ns) => FFI_Result { ok: Some( ns.iter() - .map(|fr| CFr::from(*fr)) + .map(|fr| FFI_Fr::from(*fr)) .collect::>() .into(), ), err: None, }, - None => CResult { + None => FFI_Result { ok: None, err: Some("values are Single; use get_nullifier".into()), }, @@ -1345,14 +1344,14 @@ pub fn ffi_rln_proof_values_get_nullifiers( #[ffi_export] pub fn ffi_rln_proof_values_to_bytes_le( pv: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { let mut bytes = Vec::new(); match pv.0.serialize_compressed(&mut bytes) { - Ok(()) => CResult { + Ok(()) => FFI_Result { ok: Some(bytes.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -1362,14 +1361,14 @@ pub fn ffi_rln_proof_values_to_bytes_le( #[ffi_export] pub fn ffi_rln_proof_values_to_bytes_be( pv: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { let mut bytes = Vec::new(); match CanonicalSerializeBE::serialize(&pv.0, &mut bytes) { - Ok(()) => CResult { + Ok(()) => FFI_Result { ok: Some(bytes.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -1379,13 +1378,13 @@ pub fn ffi_rln_proof_values_to_bytes_be( #[ffi_export] pub fn ffi_bytes_le_to_rln_proof_values( bytes: &repr_c::Vec, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match RLNProofValues::deserialize_compressed(&bytes[..]) { - Ok(pv) => CResult { + Ok(pv) => FFI_Result { ok: Some(Box_::new(FFI_RLNProofValues(pv))), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -1395,13 +1394,13 @@ pub fn ffi_bytes_le_to_rln_proof_values( #[ffi_export] pub fn ffi_bytes_be_to_rln_proof_values( bytes: &repr_c::Vec, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match ::deserialize(&bytes[..]) { - Ok(pv) => CResult { + Ok(pv) => FFI_Result { ok: Some(Box_::new(FFI_RLNProofValues(pv))), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -1415,19 +1414,19 @@ pub fn ffi_rln_proof_values_free(proof_values: repr_c::Box) #[ffi_export] pub fn ffi_rln_compute_id_secret( - share1_x: &CFr, - share1_y: &CFr, - share2_x: &CFr, - share2_y: &CFr, -) -> CResult, repr_c::String> { + share1_x: &FFI_Fr, + share1_y: &FFI_Fr, + share2_x: &FFI_Fr, + share2_y: &FFI_Fr, +) -> FFI_Result, repr_c::String> { let share1 = (share1_x.0, share1_y.0); let share2 = (share2_x.0, share2_y.0); match compute_id_secret(share1, share2) { - Ok(secret) => CResult { - ok: Some(Box_::new(CFr::from(*secret))), + Ok(secret) => FFI_Result { + ok: Some(Box_::new(FFI_SecretFr::from(secret))), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -1438,13 +1437,13 @@ pub fn ffi_rln_compute_id_secret( pub fn ffi_rln_recover_id_secret( proof_values_1: &repr_c::Box, proof_values_2: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match proof_values_1.0.recover_secret(&proof_values_2.0) { - Ok(secret) => CResult { - ok: Some(Box_::new(CFr::from(*secret))), + Ok(secret) => FFI_Result { + ok: Some(Box_::new(FFI_SecretFr::from(secret))), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -1456,7 +1455,7 @@ pub fn ffi_rln_recover_id_secret( #[derive_ReprC] #[repr(C)] pub struct FFI_RLNMerkleProof { - pub path_elements: repr_c::Vec, + pub path_elements: repr_c::Vec, pub path_index: repr_c::Vec, } @@ -1476,9 +1475,9 @@ pub fn ffi_rln_leaves_set(rln: &repr_c::Box) -> usize { } #[ffi_export] -pub fn ffi_rln_get_root(rln: &repr_c::Box) -> repr_c::Box { +pub fn ffi_rln_get_root(rln: &repr_c::Box) -> repr_c::Box { let root = rln.0.get_root().unwrap_or_else(|_| Fr::from(0u64)); - CFr::from(root).into() + FFI_Fr::from(root).into() } #[ffi_export] @@ -1486,13 +1485,13 @@ pub fn ffi_rln_get_subtree_root( rln: &repr_c::Box, level: usize, index: usize, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match rln.0.get_subtree_root(level, index) { - Ok(root) => CResult { - ok: Some(CFr::from(root).into()), + Ok(root) => FFI_Result { + ok: Some(FFI_Fr::from(root).into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.into()), }, @@ -1500,13 +1499,17 @@ pub fn ffi_rln_get_subtree_root( } #[ffi_export] -pub fn ffi_rln_set_leaf(rln: &mut repr_c::Box, index: usize, leaf: &CFr) -> CBoolResult { +pub fn ffi_rln_set_leaf( + rln: &mut repr_c::Box, + index: usize, + leaf: &FFI_Fr, +) -> FFI_BoolResult { match rln.0.set_leaf(index, leaf.0) { - Ok(_) => CBoolResult { + Ok(_) => FFI_BoolResult { ok: true, err: None, }, - Err(err) => CBoolResult { + Err(err) => FFI_BoolResult { ok: false, err: Some(err.into()), }, @@ -1517,15 +1520,15 @@ pub fn ffi_rln_set_leaf(rln: &mut repr_c::Box, index: usize, leaf: &CFr pub fn ffi_rln_set_leaves_from( rln: &mut repr_c::Box, index: usize, - leaves: &repr_c::Vec, -) -> CBoolResult { - let leaves_vec: Vec<_> = leaves.iter().map(|cfr| cfr.0).collect(); + leaves: &repr_c::Vec, +) -> FFI_BoolResult { + let leaves_vec: Vec<_> = leaves.iter().map(|fr| fr.0).collect(); match rln.0.set_leaves_from(index, leaves_vec) { - Ok(_) => CBoolResult { + Ok(_) => FFI_BoolResult { ok: true, err: None, }, - Err(err) => CBoolResult { + Err(err) => FFI_BoolResult { ok: false, err: Some(err.into()), }, @@ -1535,15 +1538,15 @@ pub fn ffi_rln_set_leaves_from( #[ffi_export] pub fn ffi_rln_init_tree_with_leaves( rln: &mut repr_c::Box, - leaves: &repr_c::Vec, -) -> CBoolResult { - let leaves_vec: Vec<_> = leaves.iter().map(|cfr| cfr.0).collect(); + leaves: &repr_c::Vec, +) -> FFI_BoolResult { + let leaves_vec: Vec<_> = leaves.iter().map(|fr| fr.0).collect(); match rln.0.init_tree_with_leaves(leaves_vec) { - Ok(_) => CBoolResult { + Ok(_) => FFI_BoolResult { ok: true, err: None, }, - Err(err) => CBoolResult { + Err(err) => FFI_BoolResult { ok: false, err: Some(err.into()), }, @@ -1554,13 +1557,13 @@ pub fn ffi_rln_init_tree_with_leaves( pub fn ffi_rln_get_leaf( rln: &repr_c::Box, index: usize, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match rln.0.get_leaf(index) { - Ok(leaf) => CResult { - ok: Some(CFr::from(leaf).into()), + Ok(leaf) => FFI_Result { + ok: Some(FFI_Fr::from(leaf).into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.into()), }, @@ -1570,13 +1573,13 @@ pub fn ffi_rln_get_leaf( #[ffi_export] pub fn ffi_rln_get_empty_leaves_indices( rln: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match rln.0.get_empty_leaves_indices() { - Ok(indices) => CResult { + Ok(indices) => FFI_Result { ok: Some(indices.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.into()), }, @@ -1587,17 +1590,17 @@ pub fn ffi_rln_get_empty_leaves_indices( pub fn ffi_rln_atomic_operation( rln: &mut repr_c::Box, index: usize, - leaves: &repr_c::Vec, + leaves: &repr_c::Vec, indices: &repr_c::Vec, -) -> CBoolResult { - let leaves_vec: Vec<_> = leaves.iter().map(|cfr| cfr.0).collect(); +) -> FFI_BoolResult { + let leaves_vec: Vec<_> = leaves.iter().map(|fr| fr.0).collect(); let indices_vec: Vec<_> = indices.iter().copied().collect(); match rln.0.atomic_operation(index, leaves_vec, indices_vec) { - Ok(_) => CBoolResult { + Ok(_) => FFI_BoolResult { ok: true, err: None, }, - Err(err) => CBoolResult { + Err(err) => FFI_BoolResult { ok: false, err: Some(err.into()), }, @@ -1605,13 +1608,13 @@ pub fn ffi_rln_atomic_operation( } #[ffi_export] -pub fn ffi_rln_set_next_leaf(rln: &mut repr_c::Box, leaf: &CFr) -> CBoolResult { +pub fn ffi_rln_set_next_leaf(rln: &mut repr_c::Box, leaf: &FFI_Fr) -> FFI_BoolResult { match rln.0.set_next_leaf(leaf.0) { - Ok(_) => CBoolResult { + Ok(_) => FFI_BoolResult { ok: true, err: None, }, - Err(err) => CBoolResult { + Err(err) => FFI_BoolResult { ok: false, err: Some(err.into()), }, @@ -1619,13 +1622,13 @@ pub fn ffi_rln_set_next_leaf(rln: &mut repr_c::Box, leaf: &CFr) -> CBoo } #[ffi_export] -pub fn ffi_rln_delete_leaf(rln: &mut repr_c::Box, index: usize) -> CBoolResult { +pub fn ffi_rln_delete_leaf(rln: &mut repr_c::Box, index: usize) -> FFI_BoolResult { match rln.0.delete_leaf(index) { - Ok(_) => CBoolResult { + Ok(_) => FFI_BoolResult { ok: true, err: None, }, - Err(err) => CBoolResult { + Err(err) => FFI_BoolResult { ok: false, err: Some(err.into()), }, @@ -1636,16 +1639,16 @@ pub fn ffi_rln_delete_leaf(rln: &mut repr_c::Box, index: usize) -> CBoo pub fn ffi_rln_get_merkle_proof( rln: &repr_c::Box, index: usize, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match rln.0.get_merkle_proof(index) { Ok((path_elements, path_index)) => { - let path_elements: repr_c::Vec = path_elements + let path_elements: repr_c::Vec = path_elements .iter() - .map(|fr| CFr::from(*fr)) + .map(|fr| FFI_Fr::from(*fr)) .collect::>() .into(); let path_index: repr_c::Vec = path_index.into(); - CResult { + FFI_Result { ok: Some(Box_::new(FFI_RLNMerkleProof { path_elements, path_index, @@ -1653,7 +1656,7 @@ pub fn ffi_rln_get_merkle_proof( err: None, } } - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.into()), }, @@ -1664,13 +1667,13 @@ pub fn ffi_rln_get_merkle_proof( pub fn ffi_rln_set_metadata( rln: &mut repr_c::Box, metadata: &repr_c::Vec, -) -> CBoolResult { +) -> FFI_BoolResult { match rln.0.set_metadata(metadata) { - Ok(_) => CBoolResult { + Ok(_) => FFI_BoolResult { ok: true, err: None, }, - Err(err) => CBoolResult { + Err(err) => FFI_BoolResult { ok: false, err: Some(err.into()), }, @@ -1680,13 +1683,13 @@ pub fn ffi_rln_set_metadata( #[ffi_export] pub fn ffi_rln_get_metadata( rln: &repr_c::Box, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match rln.0.get_metadata() { - Ok(metadata) => CResult { + Ok(metadata) => FFI_Result { ok: Some(metadata.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.into()), }, @@ -1694,13 +1697,13 @@ pub fn ffi_rln_get_metadata( } #[ffi_export] -pub fn ffi_rln_close(rln: &mut repr_c::Box) -> CBoolResult { +pub fn ffi_rln_close(rln: &mut repr_c::Box) -> FFI_BoolResult { match rln.0.close() { - Ok(_) => CBoolResult { + Ok(_) => FFI_BoolResult { ok: true, err: None, }, - Err(err) => CBoolResult { + Err(err) => FFI_BoolResult { ok: false, err: Some(err.into()), }, diff --git a/rln/src/ffi/ffi_utils.rs b/rln/src/ffi/ffi_utils.rs index 83a5fa22..6ef6685f 100644 --- a/rln/src/ffi/ffi_utils.rs +++ b/rln/src/ffi/ffi_utils.rs @@ -7,84 +7,85 @@ use safer_ffi::{ derive_ReprC, ffi_export, prelude::{repr_c, ReprC}, }; +use zeroize::Zeroizing; use crate::prelude::*; -// CResult +// FFI_Result #[derive_ReprC] #[repr(C)] -pub struct CResult { +pub struct FFI_Result { pub ok: Option, pub err: Option, } -// CBoolResult +// FFI_BoolResult #[derive_ReprC] #[repr(C)] -pub struct CBoolResult { +pub struct FFI_BoolResult { pub ok: bool, pub err: Option, } -// CFr +// FFI_Fr #[derive_ReprC] #[repr(opaque)] #[derive(Debug, Clone, Copy, PartialEq)] -pub struct CFr(pub(crate) Fr); +pub struct FFI_Fr(pub(crate) Fr); -impl Deref for CFr { +impl Deref for FFI_Fr { type Target = Fr; fn deref(&self) -> &Self::Target { &self.0 } } -impl From for CFr { +impl From for FFI_Fr { fn from(fr: Fr) -> Self { Self(fr) } } -impl From for repr_c::Box { - fn from(cfr: CFr) -> Self { - Box_::new(cfr) +impl From for repr_c::Box { + fn from(fr: FFI_Fr) -> Self { + Box_::new(fr) } } -impl From<&CFr> for repr_c::Box { - fn from(cfr: &CFr) -> Self { - CFr(cfr.0).into() +impl From<&FFI_Fr> for repr_c::Box { + fn from(fr: &FFI_Fr) -> Self { + FFI_Fr::from(fr.0).into() } } -impl PartialEq for CFr { +impl PartialEq for FFI_Fr { fn eq(&self, other: &Fr) -> bool { self.0 == *other } } #[ffi_export] -pub fn ffi_cfr_zero() -> repr_c::Box { - CFr::from(Fr::from(0)).into() +pub fn ffi_fr_zero() -> repr_c::Box { + FFI_Fr::from(Fr::from(0)).into() } #[ffi_export] -pub fn ffi_cfr_one() -> repr_c::Box { - CFr::from(Fr::from(1)).into() +pub fn ffi_fr_one() -> repr_c::Box { + FFI_Fr::from(Fr::from(1)).into() } #[ffi_export] -pub fn ffi_cfr_to_bytes_le(cfr: &CFr) -> CResult, repr_c::String> { +pub fn ffi_fr_to_bytes_le(fr: &FFI_Fr) -> FFI_Result, repr_c::String> { let mut bytes = Vec::new(); - match cfr.0.serialize_compressed(&mut bytes) { - Ok(()) => CResult { + match fr.0.serialize_compressed(&mut bytes) { + Ok(()) => FFI_Result { ok: Some(bytes.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -92,14 +93,14 @@ pub fn ffi_cfr_to_bytes_le(cfr: &CFr) -> CResult, repr_c::String } #[ffi_export] -pub fn ffi_cfr_to_bytes_be(cfr: &CFr) -> CResult, repr_c::String> { +pub fn ffi_fr_to_bytes_be(fr: &FFI_Fr) -> FFI_Result, repr_c::String> { let mut bytes = Vec::new(); - match CanonicalSerializeBE::serialize(&cfr.0, &mut bytes) { - Ok(()) => CResult { + match CanonicalSerializeBE::serialize(&fr.0, &mut bytes) { + Ok(()) => FFI_Result { ok: Some(bytes.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -107,13 +108,15 @@ pub fn ffi_cfr_to_bytes_be(cfr: &CFr) -> CResult, repr_c::String } #[ffi_export] -pub fn ffi_bytes_le_to_cfr(bytes: &repr_c::Vec) -> CResult, repr_c::String> { +pub fn ffi_bytes_le_to_fr( + bytes: &repr_c::Vec, +) -> FFI_Result, repr_c::String> { match Fr::deserialize_compressed(&bytes[..]) { - Ok(fr) => CResult { - ok: Some(CFr(fr).into()), + Ok(fr) => FFI_Result { + ok: Some(FFI_Fr::from(fr).into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -121,13 +124,15 @@ pub fn ffi_bytes_le_to_cfr(bytes: &repr_c::Vec) -> CResult, } #[ffi_export] -pub fn ffi_bytes_be_to_cfr(bytes: &repr_c::Vec) -> CResult, repr_c::String> { +pub fn ffi_bytes_be_to_fr( + bytes: &repr_c::Vec, +) -> FFI_Result, repr_c::String> { match ::deserialize(&bytes[..]) { - Ok(fr) => CResult { - ok: Some(CFr(fr).into()), + Ok(fr) => FFI_Result { + ok: Some(FFI_Fr::from(fr).into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -135,65 +140,98 @@ pub fn ffi_bytes_be_to_cfr(bytes: &repr_c::Vec) -> CResult, } #[ffi_export] -pub fn ffi_uint_to_cfr(value: u32) -> repr_c::Box { - CFr::from(Fr::from(value)).into() +pub fn ffi_uint_to_fr(value: u32) -> repr_c::Box { + FFI_Fr::from(Fr::from(value)).into() } #[ffi_export] -pub fn ffi_cfr_debug(cfr: Option<&CFr>) -> repr_c::String { - match cfr { - Some(cfr) => format!("{:?}", cfr.0).into(), +pub fn ffi_fr_debug(fr: Option<&FFI_Fr>) -> repr_c::String { + match fr { + Some(fr) => format!("{:?}", fr.0).into(), None => "None".into(), } } #[ffi_export] -pub fn ffi_cfr_free(cfr: repr_c::Box) { - drop(cfr); +pub fn ffi_fr_free(fr: repr_c::Box) { + drop(fr); +} + +// FFI_SecretFr (opaque secret field element, zeroized on drop) + +#[derive_ReprC] +#[repr(opaque)] +pub struct FFI_SecretFr(pub(crate) SecretFr); + +impl FFI_SecretFr { + pub fn inner(&self) -> &SecretFr { + &self.0 + } } -// Vec +impl From for FFI_SecretFr { + fn from(secret: SecretFr) -> Self { + Self(secret) + } +} #[ffi_export] -pub fn ffi_vec_cfr_new(capacity: usize) -> repr_c::Vec { +pub fn ffi_secret_fr_debug(secret: Option<&FFI_SecretFr>) -> repr_c::String { + match secret { + Some(secret) => format!("{:?}", secret.0).into(), + None => "None".into(), + } +} + +#[ffi_export] +pub fn ffi_secret_fr_free(secret: repr_c::Box) { + drop(secret); +} + +// Vec + +#[ffi_export] +pub fn ffi_vec_fr_new(capacity: usize) -> repr_c::Vec { Vec::with_capacity(capacity).into() } #[ffi_export] -pub fn ffi_vec_cfr_from_cfr(cfr: &CFr) -> repr_c::Vec { - vec![*cfr].into() +pub fn ffi_vec_fr_from_fr(fr: &FFI_Fr) -> repr_c::Vec { + vec![*fr].into() } #[ffi_export] -pub fn ffi_vec_cfr_push(v: &mut safer_ffi::Vec, cfr: &CFr) { - let mut new: Vec = std::mem::replace(v, Vec::new().into()).into(); +pub fn ffi_vec_fr_push(v: &mut safer_ffi::Vec, fr: &FFI_Fr) { + let mut new: Vec = std::mem::replace(v, Vec::new().into()).into(); if new.len() == new.capacity() { new.reserve_exact(1); } - new.push(*cfr); + new.push(*fr); *v = new.into(); } #[ffi_export] -pub fn ffi_vec_cfr_len(v: &repr_c::Vec) -> usize { +pub fn ffi_vec_fr_len(v: &repr_c::Vec) -> usize { v.len() } #[ffi_export] -pub fn ffi_vec_cfr_get(v: &repr_c::Vec, i: usize) -> Option<&CFr> { +pub fn ffi_vec_fr_get(v: &repr_c::Vec, i: usize) -> Option<&FFI_Fr> { v.get(i) } #[ffi_export] -pub fn ffi_vec_cfr_to_bytes_le(vec: &repr_c::Vec) -> CResult, repr_c::String> { - let vec_fr: Vec = vec.iter().map(|cfr| cfr.0).collect(); +pub fn ffi_vec_fr_to_bytes_le( + vec: &repr_c::Vec, +) -> FFI_Result, repr_c::String> { + let vec_fr: Vec = vec.iter().map(|fr| fr.0).collect(); let mut bytes = Vec::new(); match vec_fr.serialize_compressed(&mut bytes) { - Ok(()) => CResult { + Ok(()) => FFI_Result { ok: Some(bytes.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -201,15 +239,17 @@ pub fn ffi_vec_cfr_to_bytes_le(vec: &repr_c::Vec) -> CResult) -> CResult, repr_c::String> { - let vec_fr: Vec = vec.iter().map(|cfr| cfr.0).collect(); +pub fn ffi_vec_fr_to_bytes_be( + vec: &repr_c::Vec, +) -> FFI_Result, repr_c::String> { + let vec_fr: Vec = vec.iter().map(|fr| fr.0).collect(); let mut bytes = Vec::new(); match CanonicalSerializeBE::serialize(&vec_fr, &mut bytes) { - Ok(()) => CResult { + Ok(()) => FFI_Result { ok: Some(bytes.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -217,18 +257,18 @@ pub fn ffi_vec_cfr_to_bytes_be(vec: &repr_c::Vec) -> CResult, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match Vec::::deserialize_compressed(&bytes[..]) { Ok(vec_fr) => { - let vec_cfr: Vec = vec_fr.into_iter().map(CFr).collect(); - CResult { - ok: Some(vec_cfr.into()), + let vec_fr: Vec = vec_fr.into_iter().map(FFI_Fr).collect(); + FFI_Result { + ok: Some(vec_fr.into()), err: None, } } - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -236,18 +276,18 @@ pub fn ffi_bytes_le_to_vec_cfr( } #[ffi_export] -pub fn ffi_bytes_be_to_vec_cfr( +pub fn ffi_bytes_be_to_vec_fr( bytes: &repr_c::Vec, -) -> CResult, repr_c::String> { +) -> FFI_Result, repr_c::String> { match as CanonicalDeserializeBE>::deserialize(&bytes[..]) { Ok(vec_fr) => { - let vec_cfr: Vec = vec_fr.into_iter().map(CFr).collect(); - CResult { - ok: Some(vec_cfr.into()), + let vec_fr: Vec = vec_fr.into_iter().map(FFI_Fr).collect(); + FFI_Result { + ok: Some(vec_fr.into()), err: None, } } - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -255,10 +295,10 @@ pub fn ffi_bytes_be_to_vec_cfr( } #[ffi_export] -pub fn ffi_vec_cfr_debug(v: Option<&repr_c::Vec>) -> repr_c::String { +pub fn ffi_vec_fr_debug(v: Option<&repr_c::Vec>) -> repr_c::String { match v { Some(v) => { - let vec_fr: Vec = v.iter().map(|cfr| cfr.0).collect(); + let vec_fr: Vec = v.iter().map(|fr| fr.0).collect(); format!("{:?}", vec_fr).into() } None => "None".into(), @@ -266,21 +306,23 @@ pub fn ffi_vec_cfr_debug(v: Option<&repr_c::Vec>) -> repr_c::String { } #[ffi_export] -pub fn ffi_vec_cfr_free(v: repr_c::Vec) { +pub fn ffi_vec_fr_free(v: repr_c::Vec) { drop(v); } // Vec #[ffi_export] -pub fn ffi_vec_u8_to_bytes_le(vec: &repr_c::Vec) -> CResult, repr_c::String> { +pub fn ffi_vec_u8_to_bytes_le( + vec: &repr_c::Vec, +) -> FFI_Result, repr_c::String> { let mut bytes = Vec::new(); match vec[..].serialize_compressed(&mut bytes) { - Ok(()) => CResult { + Ok(()) => FFI_Result { ok: Some(bytes.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -288,14 +330,16 @@ pub fn ffi_vec_u8_to_bytes_le(vec: &repr_c::Vec) -> CResult, } #[ffi_export] -pub fn ffi_vec_u8_to_bytes_be(vec: &repr_c::Vec) -> CResult, repr_c::String> { +pub fn ffi_vec_u8_to_bytes_be( + vec: &repr_c::Vec, +) -> FFI_Result, repr_c::String> { let mut bytes = Vec::new(); match CanonicalSerializeBE::serialize(&vec[..], &mut bytes) { - Ok(()) => CResult { + Ok(()) => FFI_Result { ok: Some(bytes.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -303,13 +347,15 @@ pub fn ffi_vec_u8_to_bytes_be(vec: &repr_c::Vec) -> CResult, } #[ffi_export] -pub fn ffi_bytes_le_to_vec_u8(bytes: &repr_c::Vec) -> CResult, repr_c::String> { +pub fn ffi_bytes_le_to_vec_u8( + bytes: &repr_c::Vec, +) -> FFI_Result, repr_c::String> { match Vec::::deserialize_compressed(&bytes[..]) { - Ok(vec) => CResult { + Ok(vec) => FFI_Result { ok: Some(vec.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -317,13 +363,15 @@ pub fn ffi_bytes_le_to_vec_u8(bytes: &repr_c::Vec) -> CResult) -> CResult, repr_c::String> { +pub fn ffi_bytes_be_to_vec_u8( + bytes: &repr_c::Vec, +) -> FFI_Result, repr_c::String> { match as CanonicalDeserializeBE>::deserialize(&bytes[..]) { - Ok(vec) => CResult { + Ok(vec) => FFI_Result { ok: Some(vec.into()), err: None, }, - Err(err) => CResult { + Err(err) => FFI_Result { ok: None, err: Some(err.to_string().into()), }, @@ -346,61 +394,327 @@ pub fn ffi_vec_u8_free(v: repr_c::Vec) { // Hasher #[ffi_export] -pub fn ffi_hash_to_field_le(input: &repr_c::Vec) -> repr_c::Box { - CFr::from(hash_to_field_le(input)).into() +pub fn ffi_hash_to_field_le(input: &repr_c::Vec) -> repr_c::Box { + FFI_Fr::from(hash_to_field_le(input)).into() } #[ffi_export] -pub fn ffi_hash_to_field_be(input: &repr_c::Vec) -> repr_c::Box { - CFr::from(hash_to_field_be(input)).into() +pub fn ffi_hash_to_field_be(input: &repr_c::Vec) -> repr_c::Box { + FFI_Fr::from(hash_to_field_be(input)).into() } #[ffi_export] -pub fn ffi_poseidon_hash_pair(a: &CFr, b: &CFr) -> repr_c::Box { - CFr::from(poseidon_hash_pair(a.0, b.0)).into() +pub fn ffi_poseidon_hash_pair(a: &FFI_Fr, b: &FFI_Fr) -> repr_c::Box { + FFI_Fr::from(poseidon_hash_pair(a.0, b.0)).into() } -// Identity +// FFI_IdentityKeys + +#[derive_ReprC] +#[repr(opaque)] +pub struct FFI_IdentityKeys { + identity_secret: SecretFr, + id_commitment: Fr, +} #[ffi_export] -pub fn ffi_key_gen() -> repr_c::Vec { +pub fn ffi_identity_keys_generate() -> repr_c::Box { let (identity_secret, id_commitment) = keygen(); - // TODO(PR12): Leaking secret here, consider using a more secure approach to handle secrets in FFI. - vec![CFr(*identity_secret), CFr(id_commitment)].into() + Box_::new(FFI_IdentityKeys { + identity_secret, + id_commitment, + }) } #[ffi_export] -pub fn ffi_seeded_key_gen(seed: &repr_c::Vec) -> repr_c::Vec { +pub fn ffi_identity_keys_generate_seeded(seed: &repr_c::Vec) -> repr_c::Box { let (identity_secret, id_commitment) = seeded_keygen(seed); - // TODO(PR12): Leaking secret here, consider using a more secure approach to handle secrets in FFI. - vec![CFr(*identity_secret), CFr(id_commitment)].into() + Box_::new(FFI_IdentityKeys { + identity_secret, + id_commitment, + }) } -// ExtendedIdentity +#[ffi_export] +pub fn ffi_identity_keys_get_secret(identity: &FFI_IdentityKeys) -> repr_c::Box { + Box_::new(FFI_SecretFr::from(identity.identity_secret.clone())) +} + +#[ffi_export] +pub fn ffi_identity_keys_get_commitment(identity: &FFI_IdentityKeys) -> repr_c::Box { + FFI_Fr::from(identity.id_commitment).into() +} #[ffi_export] -pub fn ffi_extended_key_gen() -> repr_c::Vec { +pub fn ffi_identity_keys_to_bytes_le( + identity: &FFI_IdentityKeys, +) -> FFI_Result, repr_c::String> { + let vec_fr = Zeroizing::new(vec![*identity.identity_secret, identity.id_commitment]); + let mut bytes = Vec::new(); + match vec_fr.serialize_compressed(&mut bytes) { + Ok(()) => FFI_Result { + ok: Some(bytes.into()), + err: None, + }, + Err(err) => FFI_Result { + ok: None, + err: Some(err.to_string().into()), + }, + } +} + +#[ffi_export] +pub fn ffi_identity_keys_to_bytes_be( + identity: &FFI_IdentityKeys, +) -> FFI_Result, repr_c::String> { + let vec_fr = Zeroizing::new(vec![*identity.identity_secret, identity.id_commitment]); + let mut bytes = Vec::new(); + match CanonicalSerializeBE::serialize(&*vec_fr, &mut bytes) { + Ok(()) => FFI_Result { + ok: Some(bytes.into()), + err: None, + }, + Err(err) => FFI_Result { + ok: None, + err: Some(err.to_string().into()), + }, + } +} + +#[ffi_export] +pub fn ffi_identity_keys_from_bytes_le( + bytes: &repr_c::Vec, +) -> FFI_Result, repr_c::String> { + let mut vec_fr = match Vec::::deserialize_compressed(&bytes[..]) { + Ok(vec_fr) => Zeroizing::new(vec_fr), + Err(err) => { + return FFI_Result { + ok: None, + err: Some(err.to_string().into()), + } + } + }; + if vec_fr.len() != 2 { + return FFI_Result { + ok: None, + err: Some(format!("Expected 2 elements, got {}", vec_fr.len()).into()), + }; + } + FFI_Result { + ok: Some(Box_::new(FFI_IdentityKeys { + identity_secret: SecretFr::from(&mut vec_fr[0]), + id_commitment: vec_fr[1], + })), + err: None, + } +} + +#[ffi_export] +pub fn ffi_identity_keys_from_bytes_be( + bytes: &repr_c::Vec, +) -> FFI_Result, repr_c::String> { + let mut vec_fr = match as CanonicalDeserializeBE>::deserialize(&bytes[..]) { + Ok(vec_fr) => Zeroizing::new(vec_fr), + Err(err) => { + return FFI_Result { + ok: None, + err: Some(err.to_string().into()), + } + } + }; + if vec_fr.len() != 2 { + return FFI_Result { + ok: None, + err: Some(format!("Expected 2 elements, got {}", vec_fr.len()).into()), + }; + } + FFI_Result { + ok: Some(Box_::new(FFI_IdentityKeys { + identity_secret: SecretFr::from(&mut vec_fr[0]), + id_commitment: vec_fr[1], + })), + err: None, + } +} + +#[ffi_export] +pub fn ffi_identity_keys_free(identity: repr_c::Box) { + drop(identity); +} + +// FFI_ExtendedIdentityKeys + +#[derive_ReprC] +#[repr(opaque)] +pub struct FFI_ExtendedIdentityKeys { + identity_trapdoor: SecretFr, + identity_nullifier: SecretFr, + identity_secret: SecretFr, + id_commitment: Fr, +} + +#[ffi_export] +pub fn ffi_extended_identity_keys_generate() -> repr_c::Box { let (identity_trapdoor, identity_nullifier, identity_secret, id_commitment) = extended_keygen(); - vec![ - CFr(identity_trapdoor), - CFr(identity_nullifier), - CFr(identity_secret), - CFr(id_commitment), - ] - .into() + Box_::new(FFI_ExtendedIdentityKeys { + identity_trapdoor, + identity_nullifier, + identity_secret, + id_commitment, + }) } #[ffi_export] -pub fn ffi_seeded_extended_key_gen(seed: &repr_c::Vec) -> repr_c::Vec { +pub fn ffi_extended_identity_keys_generate_seeded( + seed: &repr_c::Vec, +) -> repr_c::Box { let (identity_trapdoor, identity_nullifier, identity_secret, id_commitment) = extended_seeded_keygen(seed); - vec![ - CFr(identity_trapdoor), - CFr(identity_nullifier), - CFr(identity_secret), - CFr(id_commitment), - ] - .into() + Box_::new(FFI_ExtendedIdentityKeys { + identity_trapdoor, + identity_nullifier, + identity_secret, + id_commitment, + }) +} + +#[ffi_export] +pub fn ffi_extended_identity_keys_get_trapdoor( + identity: &FFI_ExtendedIdentityKeys, +) -> repr_c::Box { + Box_::new(FFI_SecretFr::from(identity.identity_trapdoor.clone())) +} + +#[ffi_export] +pub fn ffi_extended_identity_keys_get_nullifier( + identity: &FFI_ExtendedIdentityKeys, +) -> repr_c::Box { + Box_::new(FFI_SecretFr::from(identity.identity_nullifier.clone())) +} + +#[ffi_export] +pub fn ffi_extended_identity_keys_get_secret( + identity: &FFI_ExtendedIdentityKeys, +) -> repr_c::Box { + Box_::new(FFI_SecretFr::from(identity.identity_secret.clone())) +} + +#[ffi_export] +pub fn ffi_extended_identity_keys_get_commitment( + identity: &FFI_ExtendedIdentityKeys, +) -> repr_c::Box { + FFI_Fr::from(identity.id_commitment).into() +} + +#[ffi_export] +pub fn ffi_extended_identity_keys_to_bytes_le( + identity: &FFI_ExtendedIdentityKeys, +) -> FFI_Result, repr_c::String> { + let vec_fr = Zeroizing::new(vec![ + *identity.identity_trapdoor, + *identity.identity_nullifier, + *identity.identity_secret, + identity.id_commitment, + ]); + let mut bytes = Vec::new(); + match vec_fr.serialize_compressed(&mut bytes) { + Ok(()) => FFI_Result { + ok: Some(bytes.into()), + err: None, + }, + Err(err) => FFI_Result { + ok: None, + err: Some(err.to_string().into()), + }, + } +} + +#[ffi_export] +pub fn ffi_extended_identity_keys_to_bytes_be( + identity: &FFI_ExtendedIdentityKeys, +) -> FFI_Result, repr_c::String> { + let vec_fr = Zeroizing::new(vec![ + *identity.identity_trapdoor, + *identity.identity_nullifier, + *identity.identity_secret, + identity.id_commitment, + ]); + let mut bytes = Vec::new(); + match CanonicalSerializeBE::serialize(&*vec_fr, &mut bytes) { + Ok(()) => FFI_Result { + ok: Some(bytes.into()), + err: None, + }, + Err(err) => FFI_Result { + ok: None, + err: Some(err.to_string().into()), + }, + } +} + +#[ffi_export] +pub fn ffi_extended_identity_keys_from_bytes_le( + bytes: &repr_c::Vec, +) -> FFI_Result, repr_c::String> { + let mut vec_fr = match Vec::::deserialize_compressed(&bytes[..]) { + Ok(vec_fr) => Zeroizing::new(vec_fr), + Err(err) => { + return FFI_Result { + ok: None, + err: Some(err.to_string().into()), + } + } + }; + if vec_fr.len() != 4 { + return FFI_Result { + ok: None, + err: Some(format!("Expected 4 elements, got {}", vec_fr.len()).into()), + }; + } + FFI_Result { + ok: Some(Box_::new(FFI_ExtendedIdentityKeys { + identity_trapdoor: SecretFr::from(&mut vec_fr[0]), + identity_nullifier: SecretFr::from(&mut vec_fr[1]), + identity_secret: SecretFr::from(&mut vec_fr[2]), + id_commitment: vec_fr[3], + })), + err: None, + } +} + +#[ffi_export] +pub fn ffi_extended_identity_keys_from_bytes_be( + bytes: &repr_c::Vec, +) -> FFI_Result, repr_c::String> { + let mut vec_fr = match as CanonicalDeserializeBE>::deserialize(&bytes[..]) { + Ok(vec_fr) => Zeroizing::new(vec_fr), + Err(err) => { + return FFI_Result { + ok: None, + err: Some(err.to_string().into()), + } + } + }; + if vec_fr.len() != 4 { + return FFI_Result { + ok: None, + err: Some(format!("Expected 4 elements, got {}", vec_fr.len()).into()), + }; + } + FFI_Result { + ok: Some(Box_::new(FFI_ExtendedIdentityKeys { + identity_trapdoor: SecretFr::from(&mut vec_fr[0]), + identity_nullifier: SecretFr::from(&mut vec_fr[1]), + identity_secret: SecretFr::from(&mut vec_fr[2]), + id_commitment: vec_fr[3], + })), + err: None, + } +} + +#[ffi_export] +pub fn ffi_extended_identity_keys_free(identity: repr_c::Box) { + drop(identity); } // CString diff --git a/rln/src/hashers.rs b/rln/src/hashers.rs index 7bada18c..15d4a48f 100644 --- a/rln/src/hashers.rs +++ b/rln/src/hashers.rs @@ -7,11 +7,11 @@ use tiny_keccak::{Hasher, Keccak}; use zeroize::Zeroize; use zerokit_utils::poseidon::{Poseidon, PoseidonError}; -use crate::circuit::Fr; +use crate::circuit::{Fr, SecretFr}; +/// TODO(backlog): Generate these parameters /// These indexed constants hardcode the supported round parameters tuples (t, RF, RN, SKIP_MATRICES) for the Bn254 scalar field. /// SKIP_MATRICES is the index of the randomly generated secure MDS matrix. -/// TODO: Generate these parameters const ROUND_PARAMS: [(usize, usize, usize, usize); 8] = [ (2, 8, 56, 0), (3, 8, 57, 0), @@ -28,7 +28,6 @@ static POSEIDON: LazyLock> = LazyLock::new(|| Poseidon::::from( /// Hashes a list of field elements using Poseidon. /// -/// /// Panics if the input length does not match any of the supported round parameters. pub fn poseidon_hash(input: &[Fr]) -> Fr { POSEIDON @@ -36,14 +35,6 @@ pub fn poseidon_hash(input: &[Fr]) -> Fr { .expect("Input length must be valid with supported round parameters") } -/// Hashes a list of field elements using Poseidon. -/// -/// Return an error if the input length does not match any of the supported round parameters. -pub fn poseidon_hash_try_from(frs: &[Fr]) -> Result { - let hash = POSEIDON.hash(frs)?; - Ok(hash) -} - /// Hashes a pair of field elements using Poseidon. /// /// No panic or error is expected since the supported round parameters include the case of two elements. @@ -53,14 +44,36 @@ pub fn poseidon_hash_pair(fr1: Fr, fr2: Fr) -> Fr { .expect("Two element input must be valid with supported round parameters") } -/// Computes identity commitment from identity secret using Poseidon hash. -pub fn poseidon_hash_secret(secret: &Fr) -> Fr { - let mut to_hash = [*secret]; +/// Hashes a list of field elements using Poseidon. +/// +/// Return an error if the input length does not match any of the supported round parameters. +pub fn poseidon_hash_list(frs: &[Fr]) -> Result { + let hash = POSEIDON.hash(frs)?; + Ok(hash) +} + +/// Computes the Poseidon hash of identity secret into a identity commitment. +/// +/// The internal copy of the secret is zeroized after hashing. +pub(crate) fn poseidon_hash_id_secret(secret: &SecretFr) -> Fr { + let mut to_hash = [**secret]; let id_commitment = poseidon_hash(&to_hash); - to_hash[0].zeroize(); // wipe the identity secret copy from the stack buffer + to_hash[0].zeroize(); // wipe the secret copy from the stack buffer id_commitment } +/// Computes the Poseidon hash of a pair of secret field elements into a new secret. +/// +/// The internal copies of the secrets are zeroized after hashing. +pub(crate) fn poseidon_hash_secret_pair(secret1: &SecretFr, secret2: &SecretFr) -> SecretFr { + let mut to_hash = [**secret1, **secret2]; + let mut hashed = poseidon_hash(&to_hash); + to_hash.zeroize(); // wipe the secret copies from the stack buffer + + // SecretFr::from wipes the intermediate hash result after wrapping it + SecretFr::from(&mut hashed) +} + /// The zerokit RLN Merkle tree Hasher. #[derive(Clone, Copy, PartialEq, Eq)] pub struct PoseidonHash; diff --git a/rln/src/pm_tree.rs b/rln/src/pm_tree.rs index a335337b..e2f082ad 100644 --- a/rln/src/pm_tree.rs +++ b/rln/src/pm_tree.rs @@ -18,7 +18,7 @@ use crate::hashers::PoseidonHash; /// The key used to store the metadata in database. const METADATA_KEY: [u8; 8] = *b"metadata"; -//TODO: Export this constant from pmtree crate instead of hardcoding it here. +// TODO(pmtree): export this constant from the pmtree crate instead of hardcoding it here. /// Maximum tree depth, limited by `pmtree` crate. const MAX_DEPTH: usize = 31; @@ -214,7 +214,7 @@ impl ZerokitMerkleTree for PmTree where D: Database, D::Config: PmTreeBackendConfig, - // TODO: Unify the two hasher traits (utils `ZerokitHasher` + pmtree `Hasher`). + // TODO(pmtree): unify the two tree hasher traits (utils `ZerokitHasher` + pmtree `Hasher`). H: ZerokitHasher + Hasher>, { type Proof = PmTreeProof; diff --git a/rln/src/prelude.rs b/rln/src/prelude.rs index 9e513efe..a07c544b 100644 --- a/rln/src/prelude.rs +++ b/rln/src/prelude.rs @@ -12,7 +12,7 @@ pub use crate::{ pub use crate::{ circuit::{ graph_from_raw, zkey_from_raw, ArkGroth16Backend, Curve, Fq, Fq2, Fr, G1Affine, - G1Projective, G2Affine, G2Projective, Graph, IdSecret, PartialProof, Proof, VerifyingKey, + G1Projective, G2Affine, G2Projective, Graph, PartialProof, Proof, SecretFr, VerifyingKey, Zkey, COMPRESS_PROOF_SIZE, DEFAULT_MAX_OUT, DEFAULT_TREE_DEPTH, }, error::{ @@ -20,8 +20,8 @@ pub use crate::{ VerifyProofError, WitnessInputMultiError, WitnessInputSingleError, }, hashers::{ - hash_to_field_be, hash_to_field_le, poseidon_hash, poseidon_hash_pair, - poseidon_hash_secret, poseidon_hash_try_from, PoseidonHash, + hash_to_field_be, hash_to_field_le, poseidon_hash, poseidon_hash_list, poseidon_hash_pair, + PoseidonHash, }, protocol::{ compute_id_secret, extended_keygen, extended_seeded_keygen, keygen, seeded_keygen, diff --git a/rln/src/protocol/keygen.rs b/rln/src/protocol/keygen.rs index ae67d7e9..5a58907c 100644 --- a/rln/src/protocol/keygen.rs +++ b/rln/src/protocol/keygen.rs @@ -1,11 +1,11 @@ -use ark_std::{rand::thread_rng, UniformRand}; +use ark_std::rand::thread_rng; use rand::SeedableRng; use rand_chacha::ChaCha20Rng; use tiny_keccak::{Hasher as _, Keccak}; use crate::{ - circuit::{Fr, IdSecret}, - hashers::{poseidon_hash_pair, poseidon_hash_secret}, + circuit::{Fr, SecretFr}, + hashers::{poseidon_hash_id_secret, poseidon_hash_secret_pair}, }; // TODO(rln-generic-hash): id_commitment (and the other keygen fns) hardcode `poseidon_hash`. To make @@ -14,10 +14,10 @@ use crate::{ /// Generates a random RLN identity using a cryptographically secure RNG. /// /// Returns `(identity_secret, id_commitment)` where the commitment is `PoseidonHash(identity_secret)`. -pub fn keygen() -> (IdSecret, Fr) { +pub fn keygen() -> (SecretFr, Fr) { let mut rng = thread_rng(); - let identity_secret = IdSecret::rand(&mut rng); - let id_commitment = poseidon_hash_secret(&identity_secret); + let identity_secret = SecretFr::rand(&mut rng); + let id_commitment = poseidon_hash_id_secret(&identity_secret); (identity_secret, id_commitment) } @@ -26,12 +26,12 @@ pub fn keygen() -> (IdSecret, Fr) { /// Returns `(identity_trapdoor, identity_nullifier, identity_secret, id_commitment)` where: /// - `identity_secret = PoseidonHash(identity_trapdoor, identity_nullifier)` /// - `id_commitment = PoseidonHash(identity_secret)` -pub fn extended_keygen() -> (Fr, Fr, Fr, Fr) { +pub fn extended_keygen() -> (SecretFr, SecretFr, SecretFr, Fr) { let mut rng = thread_rng(); - let identity_trapdoor = Fr::rand(&mut rng); - let identity_nullifier = Fr::rand(&mut rng); - let identity_secret = poseidon_hash_pair(identity_trapdoor, identity_nullifier); - let id_commitment = poseidon_hash_secret(&identity_secret); + let identity_trapdoor = SecretFr::rand(&mut rng); + let identity_nullifier = SecretFr::rand(&mut rng); + let identity_secret = poseidon_hash_secret_pair(&identity_trapdoor, &identity_nullifier); + let id_commitment = poseidon_hash_id_secret(&identity_secret); ( identity_trapdoor, identity_nullifier, @@ -44,7 +44,7 @@ pub fn extended_keygen() -> (Fr, Fr, Fr, Fr) { /// /// Uses ChaCha20 RNG seeded with Keccak-256 hash of the input. /// Returns `(identity_secret, id_commitment)`. Same input always produces the same identity. -pub fn seeded_keygen(signal: &[u8]) -> (IdSecret, Fr) { +pub fn seeded_keygen(signal: &[u8]) -> (SecretFr, Fr) { // ChaCha20 requires a seed of exactly 32 bytes. // We first hash the input seed signal to a 32 bytes array and pass this as seed to ChaCha20 let mut seed = [0; 32]; @@ -53,8 +53,8 @@ pub fn seeded_keygen(signal: &[u8]) -> (IdSecret, Fr) { hasher.finalize(&mut seed); let mut rng = ChaCha20Rng::from_seed(seed); - let identity_secret = IdSecret::rand(&mut rng); - let id_commitment = poseidon_hash_secret(&identity_secret); + let identity_secret = SecretFr::rand(&mut rng); + let id_commitment = poseidon_hash_id_secret(&identity_secret); (identity_secret, id_commitment) } @@ -63,7 +63,7 @@ pub fn seeded_keygen(signal: &[u8]) -> (IdSecret, Fr) { /// Uses ChaCha20 RNG seeded with Keccak-256 hash of the input. /// Returns `(identity_trapdoor, identity_nullifier, identity_secret, id_commitment)`. /// Same input always produces the same identity. -pub fn extended_seeded_keygen(signal: &[u8]) -> (Fr, Fr, Fr, Fr) { +pub fn extended_seeded_keygen(signal: &[u8]) -> (SecretFr, SecretFr, SecretFr, Fr) { // ChaCha20 requires a seed of exactly 32 bytes. // We first hash the input seed signal to a 32 bytes array and pass this as seed to ChaCha20 let mut seed = [0; 32]; @@ -72,10 +72,10 @@ pub fn extended_seeded_keygen(signal: &[u8]) -> (Fr, Fr, Fr, Fr) { hasher.finalize(&mut seed); let mut rng = ChaCha20Rng::from_seed(seed); - let identity_trapdoor = Fr::rand(&mut rng); - let identity_nullifier = Fr::rand(&mut rng); - let identity_secret = poseidon_hash_pair(identity_trapdoor, identity_nullifier); - let id_commitment = poseidon_hash_secret(&identity_secret); + let identity_trapdoor = SecretFr::rand(&mut rng); + let identity_nullifier = SecretFr::rand(&mut rng); + let identity_secret = poseidon_hash_secret_pair(&identity_trapdoor, &identity_nullifier); + let id_commitment = poseidon_hash_id_secret(&identity_secret); ( identity_trapdoor, identity_nullifier, diff --git a/rln/src/protocol/proof.rs b/rln/src/protocol/proof.rs index 2d7888d9..c493ad67 100644 --- a/rln/src/protocol/proof.rs +++ b/rln/src/protocol/proof.rs @@ -8,9 +8,9 @@ use super::{ zk::RecoverSecret, }; use crate::{ - circuit::{Fr, IdSecret, Proof}, + circuit::{Fr, Proof, SecretFr}, error::RecoverSecretError, - hashers::{poseidon_hash, poseidon_hash_secret, PoseidonHash}, + hashers::{poseidon_hash, poseidon_hash_id_secret, PoseidonHash}, }; #[derive(Debug, PartialEq, Clone)] @@ -89,7 +89,7 @@ impl From<&RLNWitnessInput> for RLNProofValues { impl RecoverSecret for RLNProofValues { type Error = RecoverSecretError; - fn recover_secret(&self, other: &Self) -> Result { + fn recover_secret(&self, other: &Self) -> Result { match (self, other) { (RLNProofValues::Single(s), RLNProofValues::Single(o)) => s.recover_secret(o), (RLNProofValues::Multi(s), RLNProofValues::Multi(o)) => s.recover_secret(o), @@ -117,7 +117,7 @@ pub struct RLNProofValuesSingle { // until a real second hash + circuit land. impl From<&RLNWitnessInputSingle> for RLNProofValuesSingle { fn from(w: &RLNWitnessInputSingle) -> Self { - let id_commitment = poseidon_hash_secret(&w.identity_secret); + let id_commitment = poseidon_hash_id_secret(&w.identity_secret); let leaf = poseidon_hash(&[id_commitment, w.user_message_limit]); let root = compute_tree_root::(leaf, &w.path_elements, &w.identity_path_index); @@ -141,7 +141,7 @@ impl From<&RLNWitnessInputSingle> for RLNProofValuesSingle { impl RecoverSecret for RLNProofValuesSingle { type Error = RecoverSecretError; - fn recover_secret(&self, other: &Self) -> Result { + fn recover_secret(&self, other: &Self) -> Result { if self.external_nullifier != other.external_nullifier { return Err(RecoverSecretError::ExternalNullifierMismatch( self.external_nullifier, @@ -158,7 +158,7 @@ impl RecoverSecret for RLNProofValuesSingle { impl RecoverSecret for RLNProofValuesSingle { type Error = RecoverSecretError; - fn recover_secret(&self, other: &RLNProofValuesMulti) -> Result { + fn recover_secret(&self, other: &RLNProofValuesMulti) -> Result { other.recover_secret(self) } } @@ -175,7 +175,7 @@ pub struct RLNProofValuesMulti { impl From<&RLNWitnessInputMulti> for RLNProofValuesMulti { fn from(w: &RLNWitnessInputMulti) -> Self { - let id_commitment = poseidon_hash_secret(&w.identity_secret); + let id_commitment = poseidon_hash_id_secret(&w.identity_secret); let leaf = poseidon_hash(&[id_commitment, w.user_message_limit]); let root = compute_tree_root::(leaf, &w.path_elements, &w.identity_path_index); @@ -206,7 +206,7 @@ impl From<&RLNWitnessInputMulti> for RLNProofValuesMulti { impl RecoverSecret for RLNProofValuesMulti { type Error = RecoverSecretError; - fn recover_secret(&self, other: &Self) -> Result { + fn recover_secret(&self, other: &Self) -> Result { if self.external_nullifier != other.external_nullifier { return Err(RecoverSecretError::ExternalNullifierMismatch( self.external_nullifier, @@ -243,7 +243,7 @@ impl RecoverSecret for RLNProofValuesMulti { impl RecoverSecret for RLNProofValuesMulti { type Error = RecoverSecretError; - fn recover_secret(&self, other: &RLNProofValuesSingle) -> Result { + fn recover_secret(&self, other: &RLNProofValuesSingle) -> Result { if self.external_nullifier != other.external_nullifier { return Err(RecoverSecretError::ExternalNullifierMismatch( self.external_nullifier, diff --git a/rln/src/protocol/serialize.rs b/rln/src/protocol/serialize.rs index b37ac00b..6b5022ac 100644 --- a/rln/src/protocol/serialize.rs +++ b/rln/src/protocol/serialize.rs @@ -16,7 +16,7 @@ use super::{ }, }; use crate::{ - circuit::{Fr, IdSecret, Proof, COMPRESS_PROOF_SIZE}, + circuit::{Fr, Proof, SecretFr, COMPRESS_PROOF_SIZE}, error::SerializationError, }; @@ -97,7 +97,7 @@ impl CanonicalDeserializeBE for Fr { } } -impl CanonicalSerializeBE for IdSecret { +impl CanonicalSerializeBE for SecretFr { type Error = SerializationError; fn serialize(&self, mut writer: W) -> Result<(), Self::Error> { @@ -116,7 +116,7 @@ impl CanonicalSerializeBE for IdSecret { } } -impl CanonicalDeserializeBE for IdSecret { +impl CanonicalDeserializeBE for SecretFr { type Error = SerializationError; fn deserialize(mut reader: R) -> Result { @@ -133,7 +133,7 @@ impl CanonicalDeserializeBE for IdSecret { return Err(SerializationError::NonCanonicalFieldElement); } let mut fr = Fr::from(*bigint); - Ok(IdSecret::from(&mut fr)) + Ok(SecretFr::from(&mut fr)) } } @@ -380,7 +380,7 @@ impl CanonicalDeserializeBE for RLNWitnessInputSingle { type Error = SerializationError; fn deserialize(mut reader: R) -> Result { - let identity_secret = IdSecret::deserialize(&mut reader)?; + let identity_secret = SecretFr::deserialize(&mut reader)?; let user_message_limit = Fr::deserialize(&mut reader)?; let message_id = Fr::deserialize(&mut reader)?; let path_elements = Vec::::deserialize(&mut reader)?; @@ -430,7 +430,7 @@ impl CanonicalDeserializeBE for RLNWitnessInputMulti { type Error = SerializationError; fn deserialize(mut reader: R) -> Result { - let identity_secret = IdSecret::deserialize(&mut reader)?; + let identity_secret = SecretFr::deserialize(&mut reader)?; let user_message_limit = Fr::deserialize(&mut reader)?; let path_elements = Vec::::deserialize(&mut reader)?; let identity_path_index = Vec::::deserialize(&mut reader)?; @@ -474,7 +474,7 @@ impl CanonicalDeserializeBE for RLNPartialWitnessInput { type Error = SerializationError; fn deserialize(mut reader: R) -> Result { - let identity_secret = IdSecret::deserialize(&mut reader)?; + let identity_secret = SecretFr::deserialize(&mut reader)?; let user_message_limit = Fr::deserialize(&mut reader)?; let path_elements = Vec::::deserialize(&mut reader)?; let identity_path_index = Vec::::deserialize(&mut reader)?; diff --git a/rln/src/protocol/slashing.rs b/rln/src/protocol/slashing.rs index 83a1e03d..7955cd64 100644 --- a/rln/src/protocol/slashing.rs +++ b/rln/src/protocol/slashing.rs @@ -1,7 +1,7 @@ use ark_ff::AdditiveGroup; use crate::{ - circuit::{Fr, IdSecret}, + circuit::{Fr, SecretFr}, error::RecoverSecretError, }; @@ -12,7 +12,7 @@ use crate::{ pub fn compute_id_secret( share1: (Fr, Fr), share2: (Fr, Fr), -) -> Result { +) -> Result { // Assuming a0 is the identity secret and a1 = poseidonHash([a0, external_nullifier]), // a (x,y) share satisfies the following relation // y = a_0 + x * a_1 @@ -28,7 +28,7 @@ pub fn compute_id_secret( let mut a_0 = y1 - x1 * a_1; // If shares come from the same polynomial, a0 is correctly recovered and a1 = poseidonHash([a0, external_nullifier]) - let id_secret = IdSecret::from(&mut a_0); + let id_secret = SecretFr::from(&mut a_0); Ok(id_secret) } else { Err(RecoverSecretError::DivisionByZero) diff --git a/rln/src/protocol/witness.rs b/rln/src/protocol/witness.rs index 7e7e7a2c..690dc224 100644 --- a/rln/src/protocol/witness.rs +++ b/rln/src/protocol/witness.rs @@ -7,7 +7,7 @@ use crate::{ circuit::{ error::WitnessCalcError, iden3calc::{calc_witness, calc_witness_partial}, - CalcWitness, CalcWitnessPartial, Fr, FrOrSecret, Graph, IdSecret, + CalcWitness, CalcWitnessPartial, Fr, FrOrSecret, Graph, SecretFr, }, error::{ GenerateProofError, PartialWitnessInputError, WitnessInputMultiError, @@ -22,7 +22,7 @@ pub enum RLNWitnessInput { } impl RLNWitnessInput { - pub fn identity_secret(&self) -> &IdSecret { + pub fn identity_secret(&self) -> &SecretFr { match self { Self::Single(w) => &w.identity_secret, Self::Multi(w) => &w.identity_secret, @@ -95,7 +95,7 @@ impl RLNWitnessInput { impl RLNWitnessInput { #[builder(finish_fn = build)] pub fn new_single( - identity_secret: IdSecret, + identity_secret: SecretFr, user_message_limit: Fr, path_elements: Vec, identity_path_index: Vec, @@ -134,7 +134,7 @@ impl RLNWitnessInput { #[builder(finish_fn = build)] #[allow(clippy::too_many_arguments)] pub fn new_multi( - identity_secret: IdSecret, + identity_secret: SecretFr, user_message_limit: Fr, path_elements: Vec, identity_path_index: Vec, @@ -367,7 +367,7 @@ impl CalcWitnessPartial for RLNPartialWitnessInput { #[derive(Debug, PartialEq, Clone, CanonicalSerialize, CanonicalDeserialize)] pub struct RLNWitnessInputSingle { - pub(crate) identity_secret: IdSecret, + pub(crate) identity_secret: SecretFr, pub(crate) user_message_limit: Fr, pub(crate) path_elements: Vec, pub(crate) identity_path_index: Vec, @@ -378,7 +378,7 @@ pub struct RLNWitnessInputSingle { #[derive(Debug, PartialEq, Clone, CanonicalSerialize, CanonicalDeserialize)] pub struct RLNWitnessInputMulti { - pub(crate) identity_secret: IdSecret, + pub(crate) identity_secret: SecretFr, pub(crate) user_message_limit: Fr, pub(crate) path_elements: Vec, pub(crate) identity_path_index: Vec, @@ -390,7 +390,7 @@ pub struct RLNWitnessInputMulti { #[derive(Debug, PartialEq, Clone, CanonicalSerialize, CanonicalDeserialize)] pub struct RLNPartialWitnessInput { - pub(crate) identity_secret: IdSecret, + pub(crate) identity_secret: SecretFr, pub(crate) user_message_limit: Fr, pub(crate) path_elements: Vec, pub(crate) identity_path_index: Vec, @@ -401,7 +401,7 @@ impl RLNPartialWitnessInput { #[allow(clippy::new_ret_no_self)] #[builder(start_fn = new, finish_fn = build)] pub fn create( - identity_secret: IdSecret, + identity_secret: SecretFr, user_message_limit: Fr, path_elements: Vec, identity_path_index: Vec, diff --git a/rln/src/protocol/zk.rs b/rln/src/protocol/zk.rs index da4262ae..9f14e771 100644 --- a/rln/src/protocol/zk.rs +++ b/rln/src/protocol/zk.rs @@ -4,8 +4,8 @@ use ark_std::{rand::thread_rng, UniformRand}; use crate::{ circuit::{ - qap::CircomReduction, ArkGroth16Backend, CalcWitness, CalcWitnessPartial, Fr, IdSecret, - PartialProof, Proof, + qap::CircomReduction, ArkGroth16Backend, CalcWitness, CalcWitnessPartial, Fr, PartialProof, + Proof, SecretFr, }, error::{GenerateProofError, VerifyProofError}, partial_proof::{Groth16Partial, PartialAssignment}, @@ -41,7 +41,7 @@ pub trait RLNZkProof { pub trait RecoverSecret { type Error: std::error::Error; - fn recover_secret(&self, other: &Rhs) -> Result; + fn recover_secret(&self, other: &Rhs) -> Result; } pub trait RLNPartialZkProof: RLNZkProof { diff --git a/rln/tests/ffi_rln.rs b/rln/tests/ffi_rln.rs index 68b98fe4..47060213 100644 --- a/rln/tests/ffi_rln.rs +++ b/rln/tests/ffi_rln.rs @@ -14,11 +14,11 @@ mod test { macro_rules! unwrap_ok { ($result:expr, $context:expr $(,)?) => { match $result { - CResult { + FFI_Result { ok: Some(value), err: None, } => value, - CResult { + FFI_Result { ok: None, err: Some(err), } => panic!("{} failed: {}", $context, err), @@ -27,7 +27,7 @@ mod test { }; } - fn assert_bool_ok(result: CBoolResult, context: &str) { + fn assert_bool_ok(result: FFI_BoolResult, context: &str) { assert!(result.err.is_none(), "{context} returned an error"); assert!(result.ok, "{context} returned false"); } @@ -39,27 +39,20 @@ mod test { ) } - fn random_leaves(leaf_count: usize) -> Vec { + fn random_leaves(leaf_count: usize) -> Vec { let mut rng = thread_rng(); (0..leaf_count) - .map(|_| CFr::from(Fr::rand(&mut rng))) + .map(|_| FFI_Fr::from(Fr::rand(&mut rng))) .collect() } - fn identity_pair_gen() -> (repr_c::Box, repr_c::Box) { - let keys = ffi_key_gen(); - let identity_secret: repr_c::Box = ffi_vec_cfr_get(&keys, 0).unwrap().into(); - let id_commitment: repr_c::Box = ffi_vec_cfr_get(&keys, 1).unwrap().into(); - (identity_secret, id_commitment) - } - - fn external_nullifier() -> repr_c::Box { + fn external_nullifier() -> repr_c::Box { let epoch = ffi_hash_to_field_le(&b"test-epoch".to_vec().into()); let rln_identifier = ffi_hash_to_field_le(&b"test-rln-identifier".to_vec().into()); ffi_poseidon_hash_pair(&epoch, &rln_identifier) } - fn random_signal_hash() -> repr_c::Box { + fn random_signal_hash() -> repr_c::Box { let mut rng = rand::thread_rng(); let signal: [u8; 32] = rng.gen(); ffi_hash_to_field_le(&signal.to_vec().into()) @@ -68,10 +61,12 @@ mod test { // Registers an identity, returns (identity_secret, witness) ready for proof generation fn setup_witness( rln: &mut repr_c::Box, - x: &CFr, - ) -> (repr_c::Box, repr_c::Box) { - let (identity_secret, id_commitment) = identity_pair_gen(); - let user_message_limit = ffi_uint_to_cfr(100); + x: &FFI_Fr, + ) -> (repr_c::Box, repr_c::Box) { + let identity_keys = ffi_identity_keys_generate(); + let identity_secret = ffi_identity_keys_get_secret(&identity_keys); + let id_commitment = ffi_identity_keys_get_commitment(&identity_keys); + let user_message_limit = ffi_uint_to_fr(100); let rate_commitment = ffi_poseidon_hash_pair(&id_commitment, &user_message_limit); let identity_index = ffi_rln_leaves_set(rln); @@ -86,7 +81,7 @@ mod test { ); let external_nullifier = external_nullifier(); - let message_id = ffi_uint_to_cfr(1); + let message_id = ffi_uint_to_fr(1); let witness = unwrap_ok!( ffi_rln_witness_input_new_single( @@ -200,7 +195,7 @@ mod test { let last_leaf = leaves.last().unwrap(); let last_leaf_index = LEAF_COUNT - 1; let indices: Vec = vec![last_leaf_index]; - let last_leaf_vec: Vec = vec![CFr::from(**last_leaf)]; + let last_leaf_vec: Vec = vec![FFI_Fr::from(**last_leaf)]; assert_bool_ok( ffi_rln_atomic_operation( &mut rln, @@ -238,7 +233,7 @@ mod test { let mut rng = thread_rng(); let mut rln = create_rln_instance(); - let leaf = CFr::from(Fr::rand(&mut rng)); + let leaf = FFI_Fr::from(Fr::rand(&mut rng)); let index = rng.gen_range(0..(1 << DEFAULT_TREE_DEPTH)); assert_bool_ok(ffi_rln_set_leaf(&mut rln, index, &leaf), "ffi_rln_set_leaf"); @@ -258,11 +253,11 @@ mod test { ); let received_metadata = match ffi_rln_get_metadata(&rln) { - CResult { + FFI_Result { ok: Some(metadata), err: None, } => metadata, - CResult { + FFI_Result { ok: None, err: Some(err), } => panic!("ffi_rln_get_metadata failed: {err}"), @@ -276,7 +271,7 @@ mod test { let rln = create_rln_instance(); let received_metadata = match ffi_rln_get_metadata(&rln) { - CResult { + FFI_Result { ok: Some(metadata), err: None, } => metadata, @@ -354,14 +349,14 @@ mod test { ); // Empty roots skip the root check - let empty_roots: Vec = vec![]; + let empty_roots: Vec = vec![]; assert_bool_ok( ffi_rln_verify_with_roots(&rln, &rln_proof, &empty_roots.into(), &x), "ffi_rln_verify_with_roots with empty roots", ); // Random roots do not contain the correct root - let random_roots: Vec = (0..5).map(|_| CFr::from(Fr::rand(&mut rng))).collect(); + let random_roots: Vec = (0..5).map(|_| FFI_Fr::from(Fr::rand(&mut rng))).collect(); let result = ffi_rln_verify_with_roots(&rln, &rln_proof, &random_roots.clone().into(), &x); assert!(!result.ok); @@ -384,8 +379,8 @@ mod test { // Second witness: same identity, same message id, different signal let x2 = random_signal_hash(); - let user_message_limit = ffi_uint_to_cfr(100); - let message_id = ffi_uint_to_cfr(1); + let user_message_limit = ffi_uint_to_fr(100); + let message_id = ffi_uint_to_fr(1); let external_nullifier = external_nullifier(); let merkle_proof = unwrap_ok!( ffi_rln_get_merkle_proof(&rln, 0), @@ -420,7 +415,7 @@ mod test { ffi_rln_recover_id_secret(&proof_values_1, &proof_values_2), "ffi_rln_recover_id_secret", ); - assert_eq!(*recovered, *identity_secret); + assert_eq!(**recovered.inner(), **identity_secret.inner()); // Recovery with proofs from two different identities fails let x3 = random_signal_hash(); @@ -580,7 +575,7 @@ mod test { "ffi_rln_generate_partial_proof", ); let bytes = match ffi_rln_partial_proof_to_bytes_le(&partial_proof) { - CResult { + FFI_Result { ok: Some(bytes), err: None, } => bytes, @@ -603,19 +598,20 @@ mod test { #[test] fn test_invalid_witness_input() { let mut rng = thread_rng(); - let (identity_secret, _) = identity_pair_gen(); + let identity_keys = ffi_identity_keys_generate(); + let identity_secret = ffi_identity_keys_get_secret(&identity_keys); let x = random_signal_hash(); let external_nullifier = external_nullifier(); - let path_elements: Vec = (0..DEFAULT_TREE_DEPTH) - .map(|_| CFr::from(Fr::rand(&mut rng))) + let path_elements: Vec = (0..DEFAULT_TREE_DEPTH) + .map(|_| FFI_Fr::from(Fr::rand(&mut rng))) .collect(); let identity_path_index: Vec = vec![0; DEFAULT_TREE_DEPTH]; - let user_message_limit = ffi_uint_to_cfr(100); + let user_message_limit = ffi_uint_to_fr(100); // message_id >= user_message_limit fails - let invalid_message_id = ffi_uint_to_cfr(100); + let invalid_message_id = ffi_uint_to_fr(100); let result = ffi_rln_witness_input_new_single( &identity_secret, &user_message_limit, @@ -628,8 +624,8 @@ mod test { assert!(result.ok.is_none()); // user_message_limit == 0 fails - let zero_limit = ffi_uint_to_cfr(0); - let zero_message_id = ffi_uint_to_cfr(0); + let zero_limit = ffi_uint_to_fr(0); + let zero_message_id = ffi_uint_to_fr(0); let result = ffi_rln_witness_input_new_single( &identity_secret, &zero_limit, @@ -642,7 +638,7 @@ mod test { assert!(result.ok.is_none()); // path_elements and identity_path_index length mismatch fails - let message_id = ffi_uint_to_cfr(1); + let message_id = ffi_uint_to_fr(1); let short_index: Vec = vec![0; DEFAULT_TREE_DEPTH - 1]; let result = ffi_rln_witness_input_new_single( &identity_secret, @@ -659,14 +655,15 @@ mod test { #[test] fn test_partial_witness_zero_limit() { let mut rng = thread_rng(); - let (identity_secret, _) = identity_pair_gen(); + let identity_keys = ffi_identity_keys_generate(); + let identity_secret = ffi_identity_keys_get_secret(&identity_keys); - let path_elements: Vec = (0..DEFAULT_TREE_DEPTH) - .map(|_| CFr::from(Fr::rand(&mut rng))) + let path_elements: Vec = (0..DEFAULT_TREE_DEPTH) + .map(|_| FFI_Fr::from(Fr::rand(&mut rng))) .collect(); let identity_path_index: Vec = vec![0; DEFAULT_TREE_DEPTH]; - let zero_limit = ffi_uint_to_cfr(0); + let zero_limit = ffi_uint_to_fr(0); let result = ffi_rln_partial_witness_input_new( &identity_secret, &zero_limit, @@ -681,7 +678,7 @@ mod test { let mut rng = thread_rng(); let mut rln = create_rln_instance(); let max_index = 1 << DEFAULT_TREE_DEPTH; - let leaf = CFr::from(Fr::rand(&mut rng)); + let leaf = FFI_Fr::from(Fr::rand(&mut rng)); // set_leaf beyond capacity let result = ffi_rln_set_leaf(&mut rln, max_index, &leaf); @@ -704,7 +701,7 @@ mod test { fn test_stateless_tree_ops_rejected() { let mut rln = ffi_rln_new_stateless_default(); let mut rng = thread_rng(); - let leaf = CFr::from(Fr::rand(&mut rng)); + let leaf = FFI_Fr::from(Fr::rand(&mut rng)); let result = ffi_rln_set_leaf(&mut rln, 0, &leaf); assert!(!result.ok); @@ -731,7 +728,7 @@ mod test { // Verify against the stateful tree root through verify_with_roots let root = ffi_rln_get_root(&stateful_rln); - let roots: Vec = vec![(*root)]; + let roots: Vec = vec![(*root)]; assert_bool_ok( ffi_rln_verify_with_roots(&stateless_rln, &rln_proof, &roots.into(), &x), "ffi_rln_verify_with_roots on stateless instance", @@ -746,8 +743,8 @@ mod test { let (identity_secret, witness1) = setup_witness(&mut rln, &x1); let x2 = random_signal_hash(); - let user_message_limit = ffi_uint_to_cfr(100); - let message_id = ffi_uint_to_cfr(1); + let user_message_limit = ffi_uint_to_fr(100); + let message_id = ffi_uint_to_fr(1); let external_nullifier = external_nullifier(); let merkle_proof = unwrap_ok!( ffi_rln_get_merkle_proof(&rln, 0), @@ -790,6 +787,6 @@ mod test { ffi_rln_compute_id_secret(&x1, &y1, &x2, &y2), "ffi_rln_compute_id_secret", ); - assert_eq!(*recovered, *identity_secret); + assert_eq!(**recovered.inner(), **identity_secret.inner()); } } diff --git a/rln/tests/ffi_utils.rs b/rln/tests/ffi_utils.rs index 322a0c21..02f9c24e 100644 --- a/rln/tests/ffi_utils.rs +++ b/rln/tests/ffi_utils.rs @@ -9,9 +9,9 @@ mod test { fn test_seeded_keygen_ffi() { // We generate a new identity pair from an input seed let seed_bytes: Vec = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - let res = ffi_seeded_key_gen(&seed_bytes.into()); - let identity_secret = res.first().unwrap(); - let id_commitment = res.get(1).unwrap(); + let identity_keys = ffi_identity_keys_generate_seeded(&seed_bytes.into()); + let identity_secret = ffi_identity_keys_get_secret(&identity_keys); + let id_commitment = ffi_identity_keys_get_commitment(&identity_keys); // We check against expected values let expected_identity_secret_seed_bytes = Fr::from( @@ -29,19 +29,22 @@ mod test { .unwrap(), ); - assert_eq!(*identity_secret, expected_identity_secret_seed_bytes); - assert_eq!(*id_commitment, expected_id_commitment_seed_bytes); + assert_eq!( + **identity_secret.inner(), + expected_identity_secret_seed_bytes + ); + assert_eq!(**id_commitment, expected_id_commitment_seed_bytes); } #[test] fn test_seeded_extended_keygen_ffi() { // We generate a new identity tuple from an input seed let seed_bytes: Vec = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - let key_gen = ffi_seeded_extended_key_gen(&seed_bytes.into()); - let identity_trapdoor = *key_gen[0]; - let identity_nullifier = *key_gen[1]; - let identity_secret = *key_gen[2]; - let id_commitment = *key_gen[3]; + let identity_keys = ffi_extended_identity_keys_generate_seeded(&seed_bytes.into()); + let identity_trapdoor = ffi_extended_identity_keys_get_trapdoor(&identity_keys); + let identity_nullifier = ffi_extended_identity_keys_get_nullifier(&identity_keys); + let identity_secret = ffi_extended_identity_keys_get_secret(&identity_keys); + let id_commitment = ffi_extended_identity_keys_get_commitment(&identity_keys); // We check against expected values let expected_identity_trapdoor_seed_bytes = Fr::from( @@ -73,37 +76,125 @@ mod test { .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); + assert_eq!( + **identity_trapdoor.inner(), + expected_identity_trapdoor_seed_bytes + ); + assert_eq!( + **identity_nullifier.inner(), + expected_identity_nullifier_seed_bytes + ); + assert_eq!( + **identity_secret.inner(), + expected_identity_secret_seed_bytes + ); + assert_eq!(**id_commitment, expected_id_commitment_seed_bytes); } #[test] - fn test_cfr_ffi() { - let cfr_zero = ffi_cfr_zero(); + fn test_fr_ffi() { + let ffi_fr_zero = ffi_fr_zero(); let fr_zero = Fr::from(0u8); - assert_eq!(*cfr_zero, fr_zero); + assert_eq!(*ffi_fr_zero, fr_zero); - let cfr_one = ffi_cfr_one(); + let ffi_fr_one = ffi_fr_one(); let fr_one = Fr::from(1u8); - assert_eq!(*cfr_one, fr_one); + assert_eq!(*ffi_fr_one, fr_one); - let cfr_int = ffi_uint_to_cfr(42); + let ffi_fr_int = ffi_uint_to_fr(42); let fr_int = Fr::from(42u8); - assert_eq!(*cfr_int, fr_int); + assert_eq!(*ffi_fr_int, fr_int); + + let ffi_fr_debug_str = ffi_fr_debug(Some(&ffi_fr_int)); + assert_eq!(ffi_fr_debug_str.to_string(), "42"); - let cfr_debug_str = ffi_cfr_debug(Some(&cfr_int)); - assert_eq!(cfr_debug_str.to_string(), "42"); + let identity_keys = ffi_identity_keys_generate(); + let identity_secret = ffi_identity_keys_get_secret(&identity_keys); + let expected_id_commitment = poseidon_hash(&[**identity_secret.inner()]); + assert_eq!( + **ffi_identity_keys_get_commitment(&identity_keys), + expected_id_commitment + ); + } - let key_gen = ffi_key_gen(); - 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] + fn test_identity_keys_roundtrip_ffi() { + let identity_keys = ffi_identity_keys_generate(); + let bytes = match ffi_identity_keys_to_bytes_le(&identity_keys) { + FFI_Result { + ok: Some(bytes), + err: None, + } => bytes, + FFI_Result { err: Some(err), .. } => { + panic!("ffi_identity_keys_to_bytes_le call failed: {}", err) + } + _ => unreachable!(), + }; + let restored_keys = match ffi_identity_keys_from_bytes_le(&bytes) { + FFI_Result { + ok: Some(identity_keys), + err: None, + } => identity_keys, + FFI_Result { err: Some(err), .. } => { + panic!("ffi_identity_keys_from_bytes_le call failed: {}", err) + } + _ => unreachable!(), + }; + assert_eq!( + **ffi_identity_keys_get_secret(&restored_keys).inner(), + **ffi_identity_keys_get_secret(&identity_keys).inner() + ); + assert_eq!( + **ffi_identity_keys_get_commitment(&restored_keys), + **ffi_identity_keys_get_commitment(&identity_keys) + ); + } + + #[test] + fn test_extended_identity_keys_roundtrip_ffi() { + let identity_keys = ffi_extended_identity_keys_generate(); + let bytes = match ffi_extended_identity_keys_to_bytes_le(&identity_keys) { + FFI_Result { + ok: Some(bytes), + err: None, + } => bytes, + FFI_Result { err: Some(err), .. } => { + panic!( + "ffi_extended_identity_keys_to_bytes_le call failed: {}", + err + ) + } + _ => unreachable!(), + }; + let restored_keys = match ffi_extended_identity_keys_from_bytes_le(&bytes) { + FFI_Result { + ok: Some(identity_keys), + err: None, + } => identity_keys, + FFI_Result { err: Some(err), .. } => { + panic!( + "ffi_extended_identity_keys_from_bytes_le call failed: {}", + err + ) + } + _ => unreachable!(), + }; + assert_eq!( + **ffi_extended_identity_keys_get_trapdoor(&restored_keys).inner(), + **ffi_extended_identity_keys_get_trapdoor(&identity_keys).inner() + ); + assert_eq!( + **ffi_extended_identity_keys_get_nullifier(&restored_keys).inner(), + **ffi_extended_identity_keys_get_nullifier(&identity_keys).inner() + ); + assert_eq!( + **ffi_extended_identity_keys_get_secret(&restored_keys).inner(), + **ffi_extended_identity_keys_get_secret(&identity_keys).inner() + ); + assert_eq!( + **ffi_extended_identity_keys_get_commitment(&restored_keys), + **ffi_extended_identity_keys_get_commitment(&identity_keys) + ); } #[test] @@ -113,11 +204,11 @@ mod test { let signal: Vec = signal_gen.to_vec(); let bytes_le = match ffi_vec_u8_to_bytes_le(&signal.clone().into()) { - CResult { + FFI_Result { ok: Some(bytes), err: None, } => bytes, - CResult { err: Some(err), .. } => { + FFI_Result { err: Some(err), .. } => { panic!("ffi_vec_u8_to_bytes_le call failed: {}", err) } _ => unreachable!(), @@ -127,11 +218,11 @@ mod test { assert_eq!(bytes_le.iter().copied().collect::>(), expected_le); let bytes_be = match ffi_vec_u8_to_bytes_be(&signal.clone().into()) { - CResult { + FFI_Result { ok: Some(bytes), err: None, } => bytes, - CResult { err: Some(err), .. } => { + FFI_Result { err: Some(err), .. } => { panic!("ffi_vec_u8_to_bytes_be call failed: {}", err) } _ => unreachable!(), @@ -141,11 +232,11 @@ mod test { assert_eq!(bytes_be.iter().copied().collect::>(), expected_be); let signal_from_le = match ffi_bytes_le_to_vec_u8(&bytes_le) { - CResult { + FFI_Result { ok: Some(vec_u8), err: None, } => vec_u8, - CResult { err: Some(err), .. } => { + FFI_Result { err: Some(err), .. } => { panic!("ffi_bytes_le_to_vec_u8 call failed: {}", err) } _ => unreachable!(), @@ -153,11 +244,11 @@ mod test { assert_eq!(signal_from_le.iter().copied().collect::>(), signal); let signal_from_be = match ffi_bytes_be_to_vec_u8(&bytes_be) { - CResult { + FFI_Result { ok: Some(vec_u8), err: None, } => vec_u8, - CResult { err: Some(err), .. } => { + FFI_Result { err: Some(err), .. } => { panic!("ffi_bytes_be_to_vec_u8 call failed: {}", err) } _ => unreachable!(), @@ -166,17 +257,17 @@ mod test { } #[test] - fn test_vec_cfr_ffi() { + fn test_vec_fr_ffi() { let vec_fr = [Fr::from(1u8), Fr::from(2u8), Fr::from(3u8), Fr::from(4u8)]; - let vec_cfr: Vec = vec_fr.iter().map(|fr| CFr::from(*fr)).collect(); + let ffi_vec_fr: Vec = vec_fr.iter().map(|fr| FFI_Fr::from(*fr)).collect(); - let bytes_le = match ffi_vec_cfr_to_bytes_le(&vec_cfr.clone().into()) { - CResult { + let bytes_le = match ffi_vec_fr_to_bytes_le(&ffi_vec_fr.clone().into()) { + FFI_Result { ok: Some(bytes), err: None, } => bytes, - CResult { err: Some(err), .. } => { - panic!("ffi_vec_cfr_to_bytes_le call failed: {}", err) + FFI_Result { err: Some(err), .. } => { + panic!("ffi_vec_fr_to_bytes_le call failed: {}", err) } _ => unreachable!(), }; @@ -187,13 +278,13 @@ mod test { .unwrap(); assert_eq!(bytes_le.iter().copied().collect::>(), expected_le); - let bytes_be = match ffi_vec_cfr_to_bytes_be(&vec_cfr.clone().into()) { - CResult { + let bytes_be = match ffi_vec_fr_to_bytes_be(&ffi_vec_fr.clone().into()) { + FFI_Result { ok: Some(bytes), err: None, } => bytes, - CResult { err: Some(err), .. } => { - panic!("ffi_vec_cfr_to_bytes_be call failed: {}", err) + FFI_Result { err: Some(err), .. } => { + panic!("ffi_vec_fr_to_bytes_be call failed: {}", err) } _ => unreachable!(), }; @@ -201,29 +292,35 @@ mod test { CanonicalSerializeBE::serialize(&vec_fr.to_vec(), &mut expected_be).unwrap(); assert_eq!(bytes_be.iter().copied().collect::>(), expected_be); - let vec_cfr_from_le = match ffi_bytes_le_to_vec_cfr(&bytes_le) { - CResult { - ok: Some(vec_cfr), + let ffi_vec_fr_from_le = match ffi_bytes_le_to_vec_fr(&bytes_le) { + FFI_Result { + ok: Some(ffi_vec_fr), err: None, - } => vec_cfr, - CResult { err: Some(err), .. } => { - panic!("ffi_bytes_le_to_vec_cfr call failed: {}", err) + } => ffi_vec_fr, + FFI_Result { err: Some(err), .. } => { + panic!("ffi_bytes_le_to_vec_fr call failed: {}", err) } _ => unreachable!(), }; - assert_eq!(vec_cfr_from_le.iter().copied().collect::>(), vec_cfr); + assert_eq!( + ffi_vec_fr_from_le.iter().copied().collect::>(), + ffi_vec_fr + ); - let vec_cfr_from_be = match ffi_bytes_be_to_vec_cfr(&bytes_be) { - CResult { - ok: Some(vec_cfr), + let ffi_vec_fr_from_be = match ffi_bytes_be_to_vec_fr(&bytes_be) { + FFI_Result { + ok: Some(ffi_vec_fr), err: None, - } => vec_cfr, - CResult { err: Some(err), .. } => { - panic!("ffi_bytes_be_to_vec_cfr call failed: {}", err) + } => ffi_vec_fr, + FFI_Result { err: Some(err), .. } => { + panic!("ffi_bytes_be_to_vec_fr call failed: {}", err) } _ => unreachable!(), }; - assert_eq!(vec_cfr_from_be.iter().copied().collect::>(), vec_cfr); + assert_eq!( + ffi_vec_fr_from_be.iter().copied().collect::>(), + ffi_vec_fr + ); } #[test] @@ -232,45 +329,44 @@ mod test { let signal_gen: [u8; 32] = rng.gen(); let signal: Vec = signal_gen.to_vec(); - let cfr_le_1 = ffi_hash_to_field_le(&signal.clone().into()); - let fr_le_2 = hash_to_field_le(&signal); - assert_eq!(*cfr_le_1, fr_le_2); + let ffi_fr_le = ffi_hash_to_field_le(&signal.clone().into()); + let fr_le = hash_to_field_le(&signal); + assert_eq!(*ffi_fr_le, fr_le); - let cfr_be_1 = ffi_hash_to_field_be(&signal.clone().into()); - let fr_be_2 = hash_to_field_be(&signal); - assert_eq!(*cfr_be_1, fr_be_2); + let ffi_fr_be = ffi_hash_to_field_be(&signal.clone().into()); + let fr_be = hash_to_field_be(&signal); + assert_eq!(*ffi_fr_be, fr_be); - // LE and BE interpret the hash bytes differently - assert_ne!(*cfr_le_1, *cfr_be_1); - assert_ne!(fr_le_2, fr_be_2); + assert_ne!(*ffi_fr_le, *ffi_fr_be); + assert_ne!(fr_le, fr_be); - let hash_cfr_le_1 = match ffi_cfr_to_bytes_le(&cfr_le_1) { - CResult { + let ffi_fr_le_bytes = match ffi_fr_to_bytes_le(&ffi_fr_le) { + FFI_Result { ok: Some(bytes), err: None, } => bytes.iter().copied().collect::>(), - CResult { err: Some(err), .. } => { - panic!("ffi_cfr_to_bytes_le call failed: {}", err) + FFI_Result { err: Some(err), .. } => { + panic!("ffi_fr_to_bytes_le call failed: {}", err) } _ => unreachable!(), }; - let mut hash_fr_le_2 = Vec::new(); - fr_le_2.serialize_compressed(&mut hash_fr_le_2).unwrap(); - assert_eq!(hash_cfr_le_1, hash_fr_le_2); + let mut fr_le_bytes = Vec::new(); + fr_le.serialize_compressed(&mut fr_le_bytes).unwrap(); + assert_eq!(ffi_fr_le_bytes, fr_le_bytes); - let hash_cfr_be_1 = match ffi_cfr_to_bytes_be(&cfr_be_1) { - CResult { + let ffi_fr_be_bytes = match ffi_fr_to_bytes_be(&ffi_fr_be) { + FFI_Result { ok: Some(bytes), err: None, } => bytes.iter().copied().collect::>(), - CResult { err: Some(err), .. } => { - panic!("ffi_cfr_to_bytes_be call failed: {}", err) + FFI_Result { err: Some(err), .. } => { + panic!("ffi_fr_to_bytes_be call failed: {}", err) } _ => unreachable!(), }; - let mut hash_fr_be_2 = Vec::new(); - CanonicalSerializeBE::serialize(&fr_be_2, &mut hash_fr_be_2).unwrap(); - assert_eq!(hash_cfr_be_1, hash_fr_be_2); + let mut fr_be_bytes = Vec::new(); + CanonicalSerializeBE::serialize(&fr_be, &mut fr_be_bytes).unwrap(); + assert_eq!(ffi_fr_be_bytes, fr_be_bytes); } #[test] @@ -279,7 +375,8 @@ mod test { let input_2 = Fr::from(99u8); let expected_hash = poseidon_hash_pair(input_1, input_2); - let received_hash_cfr = ffi_poseidon_hash_pair(&CFr::from(input_1), &CFr::from(input_2)); - assert_eq!(*received_hash_cfr, expected_hash); + let ffi_received_hash = + ffi_poseidon_hash_pair(&FFI_Fr::from(input_1), &FFI_Fr::from(input_2)); + assert_eq!(*ffi_received_hash, expected_hash); } } diff --git a/rln/tests/keygen.rs b/rln/tests/keygen.rs index bc0d2347..1be7278d 100644 --- a/rln/tests/keygen.rs +++ b/rln/tests/keygen.rs @@ -73,11 +73,11 @@ mod test { fn test_extended_keygen_relations() { let (trapdoor, nullifier, identity_secret, id_commitment) = extended_keygen(); - let expected_identity_secret = poseidon_hash_pair(trapdoor, nullifier); - let mut to_hash = [identity_secret]; + let expected_identity_secret = poseidon_hash_pair(*trapdoor, *nullifier); + let mut to_hash = [*identity_secret]; let expected_id_commitment = poseidon_hash(&to_hash); to_hash[0].zeroize(); - assert_eq!(identity_secret, expected_identity_secret); + assert_eq!(*identity_secret, expected_identity_secret); assert_eq!(id_commitment, expected_id_commitment); } @@ -118,9 +118,9 @@ mod test { .unwrap(), ); - assert_eq!(identity_trapdoor, expected_identity_trapdoor); - assert_eq!(identity_nullifier, expected_identity_nullifier); - assert_eq!(identity_secret, expected_identity_secret); + assert_eq!(*identity_trapdoor, expected_identity_trapdoor); + assert_eq!(*identity_nullifier, expected_identity_nullifier); + assert_eq!(*identity_secret, expected_identity_secret); assert_eq!(id_commitment, expected_id_commitment); // We check again if the identity tuple generated with the same byte array corresponds to the previously generated one diff --git a/rln/tests/proof.rs b/rln/tests/proof.rs index 14e8f70e..e54c2986 100644 --- a/rln/tests/proof.rs +++ b/rln/tests/proof.rs @@ -29,7 +29,7 @@ mod test { } fn single_witness( - id: IdSecret, + id: SecretFr, path_elements: Vec, message_id: Fr, x: Fr, @@ -49,7 +49,7 @@ mod test { } fn multi_witness( - id: IdSecret, + id: SecretFr, path_elements: Vec, message_ids: Vec, selector_used: Vec, @@ -481,7 +481,7 @@ mod test { let leaf_index = 3; let identity_secret_seed = hash_to_field_le(b"test-merkle-proof"); - let identity_secret = IdSecret::from(&mut identity_secret_seed.clone()); + let identity_secret = SecretFr::from(&mut identity_secret_seed.clone()); let mut to_hash = [*identity_secret.clone()]; let id_commitment = poseidon_hash(&to_hash); to_hash[0].zeroize(); diff --git a/rln/tests/public.rs b/rln/tests/public.rs index bc60375b..e7c9925a 100644 --- a/rln/tests/public.rs +++ b/rln/tests/public.rs @@ -74,7 +74,7 @@ mod test { fn random_rln_witness(tree_depth: usize) -> RLNWitnessInput { let mut rng = thread_rng(); - let identity_secret = IdSecret::rand(&mut rng); + let identity_secret = SecretFr::rand(&mut rng); let x = hash_to_field_le(&rng.gen::<[u8; 32]>()); let epoch = hash_to_field_le(&rng.gen::<[u8; 32]>()); let rln_identifier = hash_to_field_le(b"test-rln-identifier"); diff --git a/rln/tests/serialize.rs b/rln/tests/serialize.rs index e68b10f3..4be53f1a 100644 --- a/rln/tests/serialize.rs +++ b/rln/tests/serialize.rs @@ -266,10 +266,10 @@ mod test { fn test_id_secret_be_roundtrip() { let mut rng = thread_rng(); for _ in 0..10 { - let secret = IdSecret::rand(&mut rng); + let secret = SecretFr::rand(&mut rng); let mut buf = Vec::new(); secret.serialize(&mut buf).unwrap(); - let deser = IdSecret::deserialize(buf.as_slice()).unwrap(); + let deser = SecretFr::deserialize(buf.as_slice()).unwrap(); assert_eq!(secret, deser); assert_eq!(buf.len(), CanonicalSerializeBE::serialized_size(&secret)); } @@ -277,8 +277,8 @@ mod test { #[test] fn test_id_secret_be_known_value() { - // IdSecret(42) BE should match Fr(42) BE - same field element - let secret = IdSecret::from(&mut Fr::from(42u64)); + // SecretFr(42) BE should match Fr(42) BE - same field element + let secret = SecretFr::from(&mut Fr::from(42u64)); let mut secret_buf = Vec::new(); secret.serialize(&mut secret_buf).unwrap(); @@ -305,32 +305,32 @@ mod test { // Modulus must be rejected let modulus_be = to_be(&modulus); assert!(matches!( - IdSecret::deserialize(modulus_be.as_slice()).unwrap_err(), + SecretFr::deserialize(modulus_be.as_slice()).unwrap_err(), SerializationError::NonCanonicalFieldElement )); // All 0xFF must be rejected let max_bytes = vec![0xFF; FR_BYTE_SIZE]; assert!(matches!( - IdSecret::deserialize(max_bytes.as_slice()).unwrap_err(), + SecretFr::deserialize(max_bytes.as_slice()).unwrap_err(), SerializationError::NonCanonicalFieldElement )); // Modulus - 1 must succeed let minus_one_be = to_be(&(&modulus - 1u32)); - assert!(IdSecret::deserialize(minus_one_be.as_slice()).is_ok()); + assert!(SecretFr::deserialize(minus_one_be.as_slice()).is_ok()); } #[test] fn test_id_secret_be_insufficient_data_rejected() { let short = vec![0u8; FR_BYTE_SIZE - 1]; - assert!(IdSecret::deserialize(short.as_slice()).is_err()); - assert!(IdSecret::deserialize([].as_slice()).is_err()); + assert!(SecretFr::deserialize(short.as_slice()).is_err()); + assert!(SecretFr::deserialize([].as_slice()).is_err()); } fn make_witness_input_single() -> RLNWitnessInput { RLNWitnessInput::new_single() - .identity_secret(IdSecret::from(&mut Fr::from(42u64))) + .identity_secret(SecretFr::from(&mut Fr::from(42u64))) .user_message_limit(Fr::from(10u64)) .path_elements(vec![Fr::from(1u64), Fr::from(2u64)]) .identity_path_index(vec![0u8, 1u8]) @@ -343,7 +343,7 @@ mod test { fn make_witness_input_multi() -> RLNWitnessInput { RLNWitnessInput::new_multi() - .identity_secret(IdSecret::from(&mut Fr::from(99u64))) + .identity_secret(SecretFr::from(&mut Fr::from(99u64))) .user_message_limit(Fr::from(10u64)) .path_elements(vec![Fr::from(1u64), Fr::from(2u64)]) .identity_path_index(vec![0u8, 1u8]) @@ -357,7 +357,7 @@ mod test { fn make_partial_witness() -> RLNPartialWitnessInput { RLNPartialWitnessInput::new() - .identity_secret(IdSecret::from(&mut Fr::from(42u64))) + .identity_secret(SecretFr::from(&mut Fr::from(42u64))) .user_message_limit(Fr::from(10u64)) .path_elements(vec![Fr::from(1u64), Fr::from(2u64)]) .identity_path_index(vec![0u8, 1u8]) diff --git a/rln/tests/witness.rs b/rln/tests/witness.rs index f0af63dd..28cfaa7b 100644 --- a/rln/tests/witness.rs +++ b/rln/tests/witness.rs @@ -18,7 +18,7 @@ mod test { #[test] fn test_single_witness_validation() { let mut rng = thread_rng(); - let identity_secret = IdSecret::rand(&mut rng); + let identity_secret = SecretFr::rand(&mut rng); let user_message_limit = Fr::from(100); let (path_elements, identity_path_index) = random_merkle_proof(DEFAULT_TREE_DEPTH); let x = hash_to_field_le(&rng.gen::<[u8; 32]>()); @@ -100,7 +100,7 @@ mod test { #[test] fn test_multi_witness_validation() { let mut rng = thread_rng(); - let identity_secret = IdSecret::rand(&mut rng); + let identity_secret = SecretFr::rand(&mut rng); let user_message_limit = Fr::from(10); let (path_elements, identity_path_index) = random_merkle_proof(DEFAULT_TREE_DEPTH); let x = hash_to_field_le(&rng.gen::<[u8; 32]>()); @@ -206,7 +206,7 @@ mod test { #[test] fn test_partial_witness_validation() { let mut rng = thread_rng(); - let identity_secret = IdSecret::rand(&mut rng); + let identity_secret = SecretFr::rand(&mut rng); let (path_elements, identity_path_index) = random_merkle_proof(DEFAULT_TREE_DEPTH); // Valid partial witness @@ -249,7 +249,7 @@ mod test { let mut rng = thread_rng(); let (path_elements, identity_path_index) = random_merkle_proof(DEFAULT_TREE_DEPTH + 1); let witness = RLNWitnessInput::new_single() - .identity_secret(IdSecret::rand(&mut rng)) + .identity_secret(SecretFr::rand(&mut rng)) .user_message_limit(Fr::from(10)) .path_elements(path_elements) .identity_path_index(identity_path_index) @@ -270,7 +270,7 @@ mod test { let mut rng = thread_rng(); let (path_elements, identity_path_index) = random_merkle_proof(DEFAULT_TREE_DEPTH); let witness = RLNWitnessInput::new_multi() - .identity_secret(IdSecret::rand(&mut rng)) + .identity_secret(SecretFr::rand(&mut rng)) .user_message_limit(Fr::from(10)) .path_elements(path_elements) .identity_path_index(identity_path_index) @@ -295,7 +295,7 @@ mod test { let mut rng = thread_rng(); let (path_elements, identity_path_index) = random_merkle_proof(DEFAULT_TREE_DEPTH); let witness = RLNWitnessInput::new_multi() - .identity_secret(IdSecret::rand(&mut rng)) + .identity_secret(SecretFr::rand(&mut rng)) .user_message_limit(Fr::from(10)) .path_elements(path_elements) .identity_path_index(identity_path_index) @@ -317,7 +317,7 @@ mod test { let mut rng = thread_rng(); let (path_elements, identity_path_index) = random_merkle_proof(DEFAULT_TREE_DEPTH + 1); let partial_witness = RLNPartialWitnessInput::new() - .identity_secret(IdSecret::rand(&mut rng)) + .identity_secret(SecretFr::rand(&mut rng)) .user_message_limit(Fr::from(10)) .path_elements(path_elements) .identity_path_index(identity_path_index) @@ -330,7 +330,7 @@ mod test { fn test_finish_proof_wrong_witness_depth_fails() { let rln = RLNBuilder::stateless().build(); let mut rng = thread_rng(); - let identity_secret = IdSecret::rand(&mut rng); + let identity_secret = SecretFr::rand(&mut rng); let (path_elements, identity_path_index) = random_merkle_proof(DEFAULT_TREE_DEPTH); let partial_witness = RLNPartialWitnessInput::new() .identity_secret(identity_secret.clone()) diff --git a/utils/Cargo.toml b/utils/Cargo.toml index 371e9aed..dc6b4d07 100644 --- a/utils/Cargo.toml +++ b/utils/Cargo.toml @@ -17,6 +17,7 @@ num-bigint = { version = "0.4.6", default-features = false } serde_json = "1.0.150" rayon = "1.12.0" thiserror = "2.0.18" +zeroize = "1.8.2" [dev-dependencies] hex = "0.4.3" diff --git a/utils/src/poseidon/poseidon_hash.rs b/utils/src/poseidon/poseidon_hash.rs index 21414051..b53c1c1f 100644 --- a/utils/src/poseidon/poseidon_hash.rs +++ b/utils/src/poseidon/poseidon_hash.rs @@ -4,6 +4,7 @@ // and adapted to work over arkworks field traits and custom data structures use ark_ff::PrimeField; +use zeroize::Zeroizing; use super::{error::PoseidonError, poseidon_constants::find_poseidon_ark_and_mds}; @@ -26,7 +27,7 @@ impl Poseidon { // poseidon_params is a vector containing tuples (t, RF, RP, skip_matrices) // where: t is the rate (input length + 1), RF is the number of full rounds, RP is the number of partial rounds // and skip_matrices is a (temporary) parameter used to generate secure MDS matrices (see comments in the description of find_poseidon_ark_and_mds) - // TODO: Implement automatic generation of round parameters + // TODO(backlog): implement automatic generation of round parameters. pub fn from(poseidon_params: &[(usize, usize, usize, usize)]) -> Self { let mut read_params = Vec::>::with_capacity(poseidon_params.len()); @@ -109,7 +110,9 @@ impl Poseidon { .position(|el| el.t == t) .ok_or(PoseidonError::NoParametersForInputLength(inp.len()))?; - let mut state = vec![F::ZERO; t]; + // The state vectors hold a copy of the input, which may be secret material (identity secrets), + // Zeroizing wipes them on drop so no secret bytes remain in memory after the hash is computed. + let mut state = Zeroizing::new(vec![F::ZERO; t]); let mut state_2 = state.clone(); state[1..].clone_from_slice(inp); diff --git a/utils/tests/poseidon_hash_test.rs b/utils/tests/poseidon_hash.rs similarity index 100% rename from utils/tests/poseidon_hash_test.rs rename to utils/tests/poseidon_hash.rs