Macro to call functions with an error message with output (#141)

Another variation of our call, this time when output is used
This commit is contained in:
tyshko-rostyslav 2023-03-31 14:44:04 +02:00 committed by GitHub
parent 6ff4eeb237
commit 39bea35a6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 84 additions and 98 deletions

View File

@ -3,6 +3,8 @@
extern crate wasm_bindgen; extern crate wasm_bindgen;
extern crate web_sys; extern crate web_sys;
use std::vec::Vec;
use js_sys::{BigInt as JsBigInt, Object, Uint8Array}; use js_sys::{BigInt as JsBigInt, Object, Uint8Array};
use num_bigint::BigInt; use num_bigint::BigInt;
use rln::public::RLN; use rln::public::RLN;
@ -20,6 +22,45 @@ pub struct RLNWrapper {
instance: RLN<'static>, 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<u8> = 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<u8> = 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, // Macro to call_with_error_msg methods with arbitrary amount of arguments,
// First argument to the macro is context, // First argument to the macro is context,
// second is the actual method on `RLNWrapper` // second is the actual method on `RLNWrapper`
@ -50,6 +91,13 @@ impl ProcessArg for usize {
} }
} }
impl<T> ProcessArg for Vec<T> {
type ReturnType = Vec<T>;
fn process(self) -> Self::ReturnType {
self
}
}
impl<'a> ProcessArg for *const RLN<'a> { impl<'a> ProcessArg for *const RLN<'a> {
type ReturnType = &'a RLN<'a>; type ReturnType = &'a RLN<'a>;
fn process(self) -> Self::ReturnType { fn process(self) -> Self::ReturnType {
@ -57,20 +105,21 @@ impl<'a> ProcessArg for *const RLN<'a> {
} }
} }
trait ProcessArgRef { impl ProcessArg for *const RLNWrapper {
type ReturnType; type ReturnType = &'static RLNWrapper;
fn process(self) -> Self::ReturnType; fn process(self) -> Self::ReturnType {
unsafe { &*self }
}
} }
impl ProcessArgRef for *mut RLNWrapper { impl ProcessArg for *mut RLNWrapper {
type ReturnType = &'static mut RLNWrapper; type ReturnType = &'static mut RLNWrapper;
fn process(self) -> Self::ReturnType { fn process(self) -> Self::ReturnType {
unsafe { &mut *self } unsafe { &mut *self }
} }
} }
impl<'a> ProcessArgRef for &'a [u8] { impl<'a> ProcessArg for &'a [u8] {
type ReturnType = &'a [u8]; type ReturnType = &'a [u8];
fn process(self) -> Self::ReturnType { fn process(self) -> Self::ReturnType {
@ -167,8 +216,6 @@ pub fn generate_rln_proof_with_witness(
calculated_witness: Vec<JsBigInt>, calculated_witness: Vec<JsBigInt>,
serialized_witness: Uint8Array, serialized_witness: Uint8Array,
) -> Result<Uint8Array, String> { ) -> Result<Uint8Array, String> {
let wrapper = unsafe { &mut *ctx };
let mut witness_vec: Vec<BigInt> = vec![]; let mut witness_vec: Vec<BigInt> = vec![];
for v in calculated_witness { for v in calculated_witness {
@ -182,69 +229,36 @@ pub fn generate_rln_proof_with_witness(
); );
} }
let mut output_data: Vec<u8> = Vec::new(); call_with_output_and_error_msg!(
ctx,
if wrapper generate_rln_proof_with_witness,
.instance "could not generate proof",
.generate_rln_proof_with_witness(witness_vec, serialized_witness.to_vec(), &mut output_data) witness_vec,
.is_ok() serialized_witness.to_vec()
{ )
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())
}
} }
#[allow(clippy::not_unsafe_ptr_arg_deref)] #[allow(clippy::not_unsafe_ptr_arg_deref)]
#[wasm_bindgen(js_name = generateMembershipKey)] #[wasm_bindgen(js_name = generateMembershipKey)]
pub fn wasm_key_gen(ctx: *const RLNWrapper) -> Result<Uint8Array, String> { pub fn wasm_key_gen(ctx: *const RLNWrapper) -> Result<Uint8Array, String> {
let wrapper = unsafe { &*ctx }; call_with_output_and_error_msg!(ctx, key_gen, "could not generate membership keys")
let mut output_data: Vec<u8> = 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())
}
} }
#[allow(clippy::not_unsafe_ptr_arg_deref)] #[allow(clippy::not_unsafe_ptr_arg_deref)]
#[wasm_bindgen(js_name = generateExtendedMembershipKey)] #[wasm_bindgen(js_name = generateExtendedMembershipKey)]
pub fn wasm_extended_key_gen(ctx: *const RLNWrapper) -> Result<Uint8Array, String> { pub fn wasm_extended_key_gen(ctx: *const RLNWrapper) -> Result<Uint8Array, String> {
let wrapper = unsafe { &*ctx }; call_with_output_and_error_msg!(ctx, extended_key_gen, "could not generate membership keys")
let mut output_data: Vec<u8> = 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())
}
} }
#[allow(clippy::not_unsafe_ptr_arg_deref)] #[allow(clippy::not_unsafe_ptr_arg_deref)]
#[wasm_bindgen(js_name = generateSeededMembershipKey)] #[wasm_bindgen(js_name = generateSeededMembershipKey)]
pub fn wasm_seeded_key_gen(ctx: *const RLNWrapper, seed: Uint8Array) -> Result<Uint8Array, String> { pub fn wasm_seeded_key_gen(ctx: *const RLNWrapper, seed: Uint8Array) -> Result<Uint8Array, String> {
let wrapper = unsafe { &*ctx }; call_with_output_and_error_msg!(
let mut output_data: Vec<u8> = Vec::new(); ctx,
if wrapper seeded_key_gen,
.instance "could not generate membership key",
.seeded_key_gen(&seed.to_vec()[..], &mut output_data) &seed.to_vec()[..]
.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())
}
} }
#[allow(clippy::not_unsafe_ptr_arg_deref)] #[allow(clippy::not_unsafe_ptr_arg_deref)]
@ -253,20 +267,12 @@ pub fn wasm_seeded_extended_key_gen(
ctx: *const RLNWrapper, ctx: *const RLNWrapper,
seed: Uint8Array, seed: Uint8Array,
) -> Result<Uint8Array, String> { ) -> Result<Uint8Array, String> {
let wrapper = unsafe { &*ctx }; call_with_output_and_error_msg!(
let mut output_data: Vec<u8> = Vec::new(); ctx,
if wrapper seeded_extended_key_gen,
.instance "could not generate membership key",
.seeded_extended_key_gen(&seed.to_vec()[..], &mut output_data) &seed.to_vec()[..]
.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())
}
} }
#[allow(clippy::not_unsafe_ptr_arg_deref)] #[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_1: Uint8Array,
input_proof_data_2: Uint8Array, input_proof_data_2: Uint8Array,
) -> Result<Uint8Array, String> { ) -> Result<Uint8Array, String> {
let wrapper = unsafe { &*ctx }; call_with_output_and_error_msg!(
let mut output_data: Vec<u8> = Vec::new(); ctx,
if wrapper recover_id_secret,
.instance "could not recover id secret",
.recover_id_secret( &input_proof_data_1.to_vec()[..],
&input_proof_data_1.to_vec()[..], &input_proof_data_2.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())
}
} }
#[allow(clippy::not_unsafe_ptr_arg_deref)] #[allow(clippy::not_unsafe_ptr_arg_deref)]
@ -334,14 +329,5 @@ pub fn wasm_verify_with_roots(
#[allow(clippy::not_unsafe_ptr_arg_deref)] #[allow(clippy::not_unsafe_ptr_arg_deref)]
#[wasm_bindgen(js_name = getRoot)] #[wasm_bindgen(js_name = getRoot)]
pub fn wasm_get_root(ctx: *const RLNWrapper) -> Result<Uint8Array, String> { pub fn wasm_get_root(ctx: *const RLNWrapper) -> Result<Uint8Array, String> {
let wrapper = unsafe { &*ctx }; call_with_output_and_error_msg!(ctx, get_root, "could not obtain root")
let mut output_data: Vec<u8> = 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())
}
} }