feat: add functions for calculating witness that accepts merkle proof

This commit is contained in:
Arseniy Klempner 2024-03-21 00:26:03 -07:00
parent aaa12db70d
commit ad8c6091e6
No known key found for this signature in database
GPG Key ID: 59967D458EFBF01B
5 changed files with 128 additions and 2 deletions

2
Cargo.lock generated
View File

@ -2826,7 +2826,7 @@ dependencies = [
[[package]]
name = "rln-wasm"
version = "0.0.13"
version = "0.0.14-poc"
dependencies = [
"console_error_panic_hook",
"getrandom",

View File

@ -1,6 +1,6 @@
[package]
name = "rln-wasm"
version = "0.0.13"
version = "0.0.14-poc"
edition = "2021"
license = "MIT or Apache2"

View File

@ -4,6 +4,7 @@ extern crate wasm_bindgen;
extern crate web_sys;
use std::vec::Vec;
use rln::circuit::Fr;
use js_sys::{BigInt as JsBigInt, Object, Uint8Array};
use num_bigint::BigInt;
@ -203,6 +204,29 @@ pub fn wasm_get_serialized_rln_witness(
Ok(Uint8Array::from(&rln_witness[..]))
}
#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[wasm_bindgen(js_name = getSerializedRLNWitnessWithProof)]
pub fn wasm_get_serialized_rln_witness_with_proof(
ctx: *mut RLNWrapper,
path_elements: Uint8Array,
identity_path_index: Uint8Array,
input: Uint8Array,
) -> Result<Uint8Array, String> {
let path_elements_vec: Vec<Fr> = path_elements.to_vec().iter().map(|&x| Fr::from(x as u64)).collect();
let identity_path_index_vec: Vec<u8> = identity_path_index.to_vec();
let rln_witness = call!(
ctx,
get_serialized_rln_witness_with_proof,
path_elements_vec,
identity_path_index_vec,
&input.to_vec()[..]
)
.map_err(|err| format!("{:#?}", err))?;
Ok(Uint8Array::from(&rln_witness[..]))
}
#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[wasm_bindgen(js_name = insertMember)]
pub fn wasm_set_next_leaf(ctx: *mut RLNWrapper, input: Uint8Array) -> Result<(), String> {

View File

@ -214,6 +214,53 @@ pub fn proof_inputs_to_rln_witness(
))
}
pub fn proof_inputs_to_rln_witness_with_proof(
path_elements: Vec<Fr>,
identity_path_index: Vec<u8>,
serialized: &[u8],
) -> Result<(RLNWitnessInput, usize)> {
let mut all_read: usize = 0;
let (identity_secret, read) = bytes_le_to_fr(&serialized[all_read..]);
all_read += read;
let id_index = usize::try_from(u64::from_le_bytes(
serialized[all_read..all_read + 8].try_into()?,
))?;
all_read += 8;
let (user_message_limit, read) = bytes_le_to_fr(&serialized[all_read..]);
all_read += read;
let (message_id, read) = bytes_le_to_fr(&serialized[all_read..]);
all_read += read;
let (external_nullifier, read) = bytes_le_to_fr(&serialized[all_read..]);
all_read += read;
let signal_len = usize::try_from(u64::from_le_bytes(
serialized[all_read..all_read + 8].try_into()?,
))?;
all_read += 8;
let signal: Vec<u8> = serialized[all_read..all_read + signal_len].to_vec();
let x = hash_to_field(&signal);
Ok((
RLNWitnessInput {
identity_secret,
path_elements,
identity_path_index,
user_message_limit,
message_id,
x,
external_nullifier,
},
all_read,
))
}
/// Returns `RLNWitnessInput` given a file with JSON serialized values.
///
/// # Errors
@ -350,6 +397,41 @@ pub fn proof_values_from_witness(rln_witness: &RLNWitnessInput) -> Result<RLNPro
})
}
pub fn proof_values_from_witness_with_merkle_proof(
identity_secret: &Fr,
user_message_limit: &Fr,
path_elements: &[Fr],
identity_path_index: &[u8],
external_nullifier: &Fr,
message_id: &Fr,
x: &Fr,
) -> Result<RLNProofValues> {
message_id_range_check(message_id, user_message_limit)?;
// y share
let a_1 = poseidon_hash(&[*identity_secret, *external_nullifier, *message_id]);
let y = *identity_secret + *x * a_1;
// Nullifier
let nullifier = poseidon_hash(&[a_1]);
// Merkle tree root computations
let root = compute_tree_root(
identity_secret,
user_message_limit,
path_elements,
identity_path_index,
);
Ok(RLNProofValues {
y,
nullifier,
root,
x: *x,
external_nullifier: *external_nullifier,
})
}
pub fn serialize_proof_values(rln_proof_values: &RLNProofValues) -> Vec<u8> {
let mut serialized: Vec<u8> = Vec::new();

View File

@ -1165,6 +1165,26 @@ impl RLN<'_> {
serialize_witness(&rln_witness)
}
/// Returns the serialization of a [`RLNWitnessInput`](crate::protocol::RLNWitnessInput) populated from the identity secret, the Merkle tree index, the epoch and signal.
///
/// Input values are:
/// - `input_data`: a reader for the serialization of `[ identity_secret<32> | id_index<8> | epoch<32> | signal_len<8> | signal<var> ]`
///
/// The function returns the corresponding [`RLNWitnessInput`](crate::protocol::RLNWitnessInput) object serialized using [`rln::protocol::serialize_witness`](crate::protocol::serialize_witness)).
pub fn get_serialized_rln_witness_with_proof<R: Read>(
&mut self,
path_elements: Vec<Fr>,
identity_path_index: Vec<u8>,
mut input_data: R,
) -> Result<Vec<u8>> {
// We read input RLN witness and we serialize_compressed it
let mut witness_byte: Vec<u8> = Vec::new();
input_data.read_to_end(&mut witness_byte)?;
let (rln_witness, _) = proof_inputs_to_rln_witness_with_proof(path_elements, identity_path_index, &witness_byte)?;
serialize_witness(&rln_witness)
}
/// Converts a byte serialization of a [`RLNWitnessInput`](crate::protocol::RLNWitnessInput) object to the corresponding JSON serialization.
///
/// Input values are: