From 39bea35a6da5bc80adef78a2d95c8920c90a1503 Mon Sep 17 00:00:00 2001 From: tyshko-rostyslav <122977916+tyshko-rostyslav@users.noreply.github.com> Date: Fri, 31 Mar 2023 14:44:04 +0200 Subject: [PATCH] Macro to call functions with an error message with output (#141) Another variation of our call, this time when output is used --- rln-wasm/src/lib.rs | 182 ++++++++++++++++++++------------------------ 1 file changed, 84 insertions(+), 98 deletions(-) diff --git a/rln-wasm/src/lib.rs b/rln-wasm/src/lib.rs index e6f031c..98ce811 100644 --- a/rln-wasm/src/lib.rs +++ b/rln-wasm/src/lib.rs @@ -3,6 +3,8 @@ extern crate wasm_bindgen; extern crate web_sys; +use std::vec::Vec; + use js_sys::{BigInt as JsBigInt, Object, Uint8Array}; use num_bigint::BigInt; use rln::public::RLN; @@ -20,6 +22,45 @@ pub struct RLNWrapper { instance: RLN<'static>, } +// Macro to call methods with arbitrary amount of arguments, +// which have the last argument is output buffer pointer +// First argument to the macro is context, +// second is the actual method on `RLN` +// third is the aforementioned output buffer argument +// rest are all other arguments to the method +macro_rules! call_with_output_and_error_msg { + // this variant is needed for the case when + // there are zero other arguments + ($instance:expr, $method:ident, $error_msg:expr) => { + { + let mut output_data: Vec = Vec::new(); + let new_instance = $instance.process(); + if let Err(err) = new_instance.instance.$method(&mut output_data) { + std::mem::forget(output_data); + Err(format!("Msg: {:#?}, Error: {:#?}", $error_msg, err)) + } else { + let result = Uint8Array::from(&output_data[..]); + std::mem::forget(output_data); + Ok(result) + } + } + }; + ($instance:expr, $method:ident, $error_msg:expr, $( $arg:expr ),* ) => { + { + let mut output_data: Vec = Vec::new(); + let new_instance = $instance.process(); + if let Err(err) = new_instance.instance.$method($($arg.process()),*, &mut output_data) { + std::mem::forget(output_data); + Err(format!("Msg: {:#?}, Error: {:#?}", $error_msg, err)) + } else { + let result = Uint8Array::from(&output_data[..]); + std::mem::forget(output_data); + Ok(result) + } + } + }; +} + // Macro to call_with_error_msg methods with arbitrary amount of arguments, // First argument to the macro is context, // second is the actual method on `RLNWrapper` @@ -50,6 +91,13 @@ impl ProcessArg for usize { } } +impl ProcessArg for Vec { + type ReturnType = Vec; + fn process(self) -> Self::ReturnType { + self + } +} + impl<'a> ProcessArg for *const RLN<'a> { type ReturnType = &'a RLN<'a>; fn process(self) -> Self::ReturnType { @@ -57,20 +105,21 @@ impl<'a> ProcessArg for *const RLN<'a> { } } -trait ProcessArgRef { - type ReturnType; - fn process(self) -> Self::ReturnType; +impl ProcessArg for *const RLNWrapper { + type ReturnType = &'static RLNWrapper; + fn process(self) -> Self::ReturnType { + unsafe { &*self } + } } -impl ProcessArgRef for *mut RLNWrapper { +impl ProcessArg for *mut RLNWrapper { type ReturnType = &'static mut RLNWrapper; - fn process(self) -> Self::ReturnType { unsafe { &mut *self } } } -impl<'a> ProcessArgRef for &'a [u8] { +impl<'a> ProcessArg for &'a [u8] { type ReturnType = &'a [u8]; fn process(self) -> Self::ReturnType { @@ -167,8 +216,6 @@ pub fn generate_rln_proof_with_witness( calculated_witness: Vec, serialized_witness: Uint8Array, ) -> Result { - let wrapper = unsafe { &mut *ctx }; - let mut witness_vec: Vec = vec![]; for v in calculated_witness { @@ -182,69 +229,36 @@ pub fn generate_rln_proof_with_witness( ); } - let mut output_data: Vec = Vec::new(); - - if wrapper - .instance - .generate_rln_proof_with_witness(witness_vec, serialized_witness.to_vec(), &mut output_data) - .is_ok() - { - let result = Uint8Array::from(&output_data[..]); - std::mem::forget(output_data); - Ok(result) - } else { - std::mem::forget(output_data); - Err("could not generate proof".into()) - } + call_with_output_and_error_msg!( + ctx, + generate_rln_proof_with_witness, + "could not generate proof", + witness_vec, + serialized_witness.to_vec() + ) } #[allow(clippy::not_unsafe_ptr_arg_deref)] #[wasm_bindgen(js_name = generateMembershipKey)] pub fn wasm_key_gen(ctx: *const RLNWrapper) -> Result { - let wrapper = unsafe { &*ctx }; - let mut output_data: Vec = Vec::new(); - if wrapper.instance.key_gen(&mut output_data).is_ok() { - let result = Uint8Array::from(&output_data[..]); - std::mem::forget(output_data); - Ok(result) - } else { - std::mem::forget(output_data); - Err("could not generate membership keys".into()) - } + call_with_output_and_error_msg!(ctx, key_gen, "could not generate membership keys") } #[allow(clippy::not_unsafe_ptr_arg_deref)] #[wasm_bindgen(js_name = generateExtendedMembershipKey)] pub fn wasm_extended_key_gen(ctx: *const RLNWrapper) -> Result { - let wrapper = unsafe { &*ctx }; - let mut output_data: Vec = Vec::new(); - if wrapper.instance.extended_key_gen(&mut output_data).is_ok() { - let result = Uint8Array::from(&output_data[..]); - std::mem::forget(output_data); - Ok(result) - } else { - std::mem::forget(output_data); - Err("could not generate membership keys".into()) - } + call_with_output_and_error_msg!(ctx, extended_key_gen, "could not generate membership keys") } #[allow(clippy::not_unsafe_ptr_arg_deref)] #[wasm_bindgen(js_name = generateSeededMembershipKey)] pub fn wasm_seeded_key_gen(ctx: *const RLNWrapper, seed: Uint8Array) -> Result { - let wrapper = unsafe { &*ctx }; - let mut output_data: Vec = Vec::new(); - if wrapper - .instance - .seeded_key_gen(&seed.to_vec()[..], &mut output_data) - .is_ok() - { - let result = Uint8Array::from(&output_data[..]); - std::mem::forget(output_data); - Ok(result) - } else { - std::mem::forget(output_data); - Err("could not generate membership key".into()) - } + call_with_output_and_error_msg!( + ctx, + seeded_key_gen, + "could not generate membership key", + &seed.to_vec()[..] + ) } #[allow(clippy::not_unsafe_ptr_arg_deref)] @@ -253,20 +267,12 @@ pub fn wasm_seeded_extended_key_gen( ctx: *const RLNWrapper, seed: Uint8Array, ) -> Result { - let wrapper = unsafe { &*ctx }; - let mut output_data: Vec = Vec::new(); - if wrapper - .instance - .seeded_extended_key_gen(&seed.to_vec()[..], &mut output_data) - .is_ok() - { - let result = Uint8Array::from(&output_data[..]); - std::mem::forget(output_data); - Ok(result) - } else { - std::mem::forget(output_data); - Err("could not generate membership key".into()) - } + call_with_output_and_error_msg!( + ctx, + seeded_extended_key_gen, + "could not generate membership key", + &seed.to_vec()[..] + ) } #[allow(clippy::not_unsafe_ptr_arg_deref)] @@ -276,24 +282,13 @@ pub fn wasm_recover_id_secret( input_proof_data_1: Uint8Array, input_proof_data_2: Uint8Array, ) -> Result { - let wrapper = unsafe { &*ctx }; - let mut output_data: Vec = Vec::new(); - if wrapper - .instance - .recover_id_secret( - &input_proof_data_1.to_vec()[..], - &input_proof_data_2.to_vec()[..], - &mut output_data, - ) - .is_ok() - { - let result = Uint8Array::from(&output_data[..]); - std::mem::forget(output_data); - Ok(result) - } else { - std::mem::forget(output_data); - Err("could not recover id secret".into()) - } + call_with_output_and_error_msg!( + ctx, + recover_id_secret, + "could not recover id secret", + &input_proof_data_1.to_vec()[..], + &input_proof_data_2.to_vec()[..] + ) } #[allow(clippy::not_unsafe_ptr_arg_deref)] @@ -334,14 +329,5 @@ pub fn wasm_verify_with_roots( #[allow(clippy::not_unsafe_ptr_arg_deref)] #[wasm_bindgen(js_name = getRoot)] pub fn wasm_get_root(ctx: *const RLNWrapper) -> Result { - let wrapper = unsafe { &*ctx }; - let mut output_data: Vec = Vec::new(); - if wrapper.instance.get_root(&mut output_data).is_ok() { - let result = Uint8Array::from(&output_data[..]); - std::mem::forget(output_data); - Ok(result) - } else { - std::mem::forget(output_data); - Err("could not obtain root".into()) - } + call_with_output_and_error_msg!(ctx, get_root, "could not obtain root") }