From 06b5df890a7328f6a20e370a52865748d1a54dc9 Mon Sep 17 00:00:00 2001 From: Tom French Date: Fri, 5 May 2023 12:02:40 +0100 Subject: [PATCH] chore: use `WASMValue` for wasm args Co-authored-by: Blaine Bublitz --- src/acvm_interop/smart_contract.rs | 3 +- src/composer.rs | 37 ++++++--------------- src/lib.rs | 52 +++++++++++++++++++++++------- src/pedersen.rs | 13 ++------ src/pippenger.rs | 12 ++----- src/scalar_mul.rs | 4 +-- src/schnorr.rs | 34 +++++++------------ 7 files changed, 70 insertions(+), 85 deletions(-) diff --git a/src/acvm_interop/smart_contract.rs b/src/acvm_interop/smart_contract.rs index 477fe91b..3bb0b899 100644 --- a/src/acvm_interop/smart_contract.rs +++ b/src/acvm_interop/smart_contract.rs @@ -36,7 +36,6 @@ impl SmartContract for Barretenberg { impl SmartContract for Barretenberg { fn eth_contract_from_vk(&self, verification_key: &[u8]) -> String { use crate::wasm::POINTER_BYTES; - use wasmer::Value; let g2 = G2::new(); @@ -50,7 +49,7 @@ impl SmartContract for Barretenberg { let contract_size = self .call_multiple( "acir_proofs_get_solidity_verifier", - vec![&g2_ptr, &vk_ptr, &Value::I32(contract_ptr_ptr as i32)], + vec![&g2_ptr, &vk_ptr, &contract_ptr_ptr.into()], ) .value(); let contract_size: usize = contract_size.unwrap_i32() as usize; diff --git a/src/composer.rs b/src/composer.rs index adf682ae..35987365 100644 --- a/src/composer.rs +++ b/src/composer.rs @@ -211,7 +211,7 @@ impl Composer for Barretenberg { let circuit_size = self .call("acir_proofs_get_total_circuit_size", &cs_ptr) - .into_i32(); + .i32(); let circuit_size = u32::try_from(circuit_size).expect("circuit cannot have negative number of gates"); @@ -226,7 +226,7 @@ impl Composer for Barretenberg { let circuit_size = self .call("acir_proofs_get_exact_circuit_size", &cs_ptr) - .into_i32(); + .i32(); let circuit_size = u32::try_from(circuit_size).expect("circuit cannot have negative number of gates"); @@ -237,7 +237,6 @@ impl Composer for Barretenberg { fn compute_proving_key(&self, constraint_system: &ConstraintSystem) -> Vec { use super::wasm::POINTER_BYTES; - use wasmer::Value; let cs_buf = constraint_system.to_bytes(); let cs_ptr = self.allocate(&cs_buf); @@ -246,13 +245,11 @@ impl Composer for Barretenberg { // `pk_ptr_ptr` is a pointer to a pointer which holds the proving key. let pk_ptr_ptr: usize = 0; - let pk_size = self - .call_multiple( - "acir_proofs_init_proving_key", - vec![&cs_ptr, &Value::I32(pk_ptr_ptr as i32)], - ) - .value(); - let pk_size: usize = pk_size.unwrap_i32() as usize; + let pk_size = self.call_multiple( + "acir_proofs_init_proving_key", + vec![&cs_ptr, &pk_ptr_ptr.into()], + ); + let pk_size: usize = pk_size.i32() as usize; // We then need to read the pointer at `pk_ptr_ptr` to get the key's location // and then slice memory again at `pk_ptr` to get the proving key. @@ -269,7 +266,6 @@ impl Composer for Barretenberg { proving_key: &[u8], ) -> Vec { use super::wasm::POINTER_BYTES; - use wasmer::Value; let circuit_size = self.get_circuit_size(constraint_system); let CRS { @@ -287,12 +283,7 @@ impl Composer for Barretenberg { let vk_size = self .call_multiple( "acir_proofs_init_verification_key", - vec![ - &pippenger_ptr, - &g2_ptr, - &pk_ptr, - &Value::I32(vk_ptr_ptr as i32), - ], + vec![&pippenger_ptr, &g2_ptr, &pk_ptr, &vk_ptr_ptr.into()], ) .value(); let vk_size: usize = vk_size.unwrap_i32() as usize; @@ -313,7 +304,6 @@ impl Composer for Barretenberg { proving_key: &[u8], ) -> Vec { use super::wasm::POINTER_BYTES; - use wasmer::Value; let circuit_size = self.get_circuit_size(constraint_system); let CRS { @@ -341,7 +331,7 @@ impl Composer for Barretenberg { &pk_ptr, &cs_ptr, &witness_ptr, - &Value::I32(0), + &0.into(), ], ) .value(); @@ -369,7 +359,6 @@ impl Composer for Barretenberg { public_inputs: Assignments, verification_key: &[u8], ) -> bool { - use wasmer::Value; let g2_data = G2::new().data; // Barretenberg expects public inputs to be prepended onto the proof @@ -384,13 +373,7 @@ impl Composer for Barretenberg { let verified = self .call_multiple( "acir_proofs_verify_proof", - vec![ - &g2_ptr, - &vk_ptr, - &cs_ptr, - &proof_ptr, - &Value::I32(proof.len() as i32), - ], + vec![&g2_ptr, &vk_ptr, &cs_ptr, &proof_ptr, &proof.len().into()], ) .value(); diff --git a/src/lib.rs b/src/lib.rs index 228b4bc9..fe3acd78 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -101,19 +101,46 @@ mod wasm { memory: Memory, } - /// A wrapper around the return value from a WASM call. + /// A wrapper around the arguments or return value from a WASM call. /// Notice, `Option` is used because not every call returns a value, /// some calls are simply made to free a pointer or manipulate the heap. - #[derive(Debug)] + #[derive(Debug, Clone)] pub(super) struct WASMValue(Option); impl WASMValue { pub(super) fn value(self) -> Value { self.0.unwrap() } - pub(super) fn into_i32(self) -> i32 { + + pub(super) fn i32(self) -> i32 { i32::try_from(self.0.unwrap()).expect("expected an i32 value") } + + pub(super) fn bool(self) -> bool { + match self.i32() { + 0 => false, + 1 => true, + _ => panic!("expected a boolean value"), + } + } + } + + impl From for WASMValue { + fn from(value: usize) -> Self { + WASMValue(Some(Value::I32(value as i32))) + } + } + + impl From for WASMValue { + fn from(value: i32) -> Self { + WASMValue(Some(Value::I32(value))) + } + } + + impl From for WASMValue { + fn from(value: Value) -> Self { + WASMValue(Some(value)) + } } impl Barretenberg { @@ -156,15 +183,18 @@ mod wasm { .collect(); } - pub(super) fn call(&self, name: &str, param: &Value) -> WASMValue { + pub(super) fn call(&self, name: &str, param: &WASMValue) -> WASMValue { self.call_multiple(name, vec![param]) } - pub(super) fn call_multiple(&self, name: &str, params: Vec<&Value>) -> WASMValue { + pub(super) fn call_multiple(&self, name: &str, params: Vec<&WASMValue>) -> WASMValue { // We take in a reference to values, since they do not implement Copy. // We then clone them inside of this function, so that the API does not have a bunch of Clones everywhere - let params: Vec<_> = params.into_iter().cloned().collect(); + let params: Vec = params + .into_iter() + .map(|param| param.clone().value()) + .collect(); let func = self.instance.exports.get_function(name).unwrap(); let option_value = func.call(¶ms).unwrap().first().cloned(); @@ -172,22 +202,20 @@ mod wasm { } /// Creates a pointer and allocates the bytes that the pointer references to, to the heap - pub(super) fn allocate(&self, bytes: &[u8]) -> Value { - let ptr = self - .call("bbmalloc", &Value::I32(bytes.len() as i32)) - .value(); + pub(super) fn allocate(&self, bytes: &[u8]) -> WASMValue { + let ptr = self.call("bbmalloc", &bytes.len().into()).value(); let i32_bytes = ptr.unwrap_i32().to_be_bytes(); let u32_bytes = u32::from_be_bytes(i32_bytes); self.transfer_to_heap(bytes, u32_bytes as usize); - ptr + ptr.into() } /// Frees a pointer. /// Notice we consume the Value, if you clone the value before passing it to free /// It most likely is a bug - pub(super) fn free(&self, pointer: Value) { + pub(super) fn free(&self, pointer: WASMValue) { self.call("bbfree", &pointer); } } diff --git a/src/pedersen.rs b/src/pedersen.rs index f5732ba9..6d26416e 100644 --- a/src/pedersen.rs +++ b/src/pedersen.rs @@ -52,7 +52,6 @@ impl Pedersen for Barretenberg { impl Pedersen for Barretenberg { fn compress_native(&self, left: &FieldElement, right: &FieldElement) -> FieldElement { use super::FIELD_BYTES; - use wasmer::Value; let lhs_ptr: usize = 0; let rhs_ptr: usize = lhs_ptr + FIELD_BYTES; @@ -63,11 +62,7 @@ impl Pedersen for Barretenberg { self.call_multiple( "pedersen_plookup_compress_fields", - vec![ - &Value::I32(lhs_ptr as i32), - &Value::I32(rhs_ptr as i32), - &Value::I32(result_ptr as i32), - ], + vec![&lhs_ptr.into(), &rhs_ptr.into(), &result_ptr.into()], ); let result_bytes = self.slice_memory(result_ptr, FIELD_BYTES); @@ -78,7 +73,6 @@ impl Pedersen for Barretenberg { fn compress_many(&self, inputs: Vec) -> FieldElement { use super::FIELD_BYTES; use crate::barretenberg_structures::Assignments; - use wasmer::Value; let input_buf = Assignments::from(inputs).to_bytes(); let input_ptr = self.allocate(&input_buf); @@ -86,7 +80,7 @@ impl Pedersen for Barretenberg { self.call_multiple( "pedersen_plookup_compress", - vec![&input_ptr, &Value::I32(result_ptr as i32)], + vec![&input_ptr, &result_ptr.into()], ); let result_bytes = self.slice_memory(result_ptr, FIELD_BYTES); @@ -96,7 +90,6 @@ impl Pedersen for Barretenberg { fn encrypt(&self, inputs: Vec) -> (FieldElement, FieldElement) { use super::FIELD_BYTES; use crate::barretenberg_structures::Assignments; - use wasmer::Value; let input_buf = Assignments::from(inputs).to_bytes(); let input_ptr = self.allocate(&input_buf); @@ -104,7 +97,7 @@ impl Pedersen for Barretenberg { self.call_multiple( "pedersen_plookup_commit", - vec![&input_ptr, &Value::I32(result_ptr as i32)], + vec![&input_ptr, &result_ptr.into()], ); let result_bytes = self.slice_memory(result_ptr, 2 * FIELD_BYTES); diff --git a/src/pippenger.rs b/src/pippenger.rs index 3232fc06..66e05fa8 100644 --- a/src/pippenger.rs +++ b/src/pippenger.rs @@ -4,7 +4,7 @@ pub(crate) struct Pippenger { #[cfg(feature = "native")] pippenger_ptr: *mut std::os::raw::c_void, #[cfg(not(feature = "native"))] - pippenger_ptr: wasmer::Value, + pippenger_ptr: crate::wasm::WASMValue, } #[cfg(feature = "native")] @@ -16,7 +16,7 @@ impl Pippenger { #[cfg(not(feature = "native"))] impl Pippenger { - pub(crate) fn pointer(&self) -> wasmer::Value { + pub(crate) fn pointer(&self) -> crate::wasm::WASMValue { self.pippenger_ptr.clone() } } @@ -34,18 +34,12 @@ impl Barretenberg { impl Barretenberg { pub(crate) fn get_pippenger(&self, crs_data: &[u8]) -> Pippenger { use super::FIELD_BYTES; - use wasmer::Value; let num_points = crs_data.len() / (2 * FIELD_BYTES); let crs_ptr = self.allocate(crs_data); - let pippenger_ptr = self - .call_multiple( - "new_pippenger", - vec![&crs_ptr, &Value::I32(num_points as i32)], - ) - .value(); + let pippenger_ptr = self.call_multiple("new_pippenger", vec![&crs_ptr, &num_points.into()]); self.free(crs_ptr); diff --git a/src/scalar_mul.rs b/src/scalar_mul.rs index 817142ba..5c48e417 100644 --- a/src/scalar_mul.rs +++ b/src/scalar_mul.rs @@ -26,15 +26,13 @@ impl ScalarMul for Barretenberg { #[cfg(not(feature = "native"))] impl ScalarMul for Barretenberg { fn fixed_base(&self, input: &FieldElement) -> (FieldElement, FieldElement) { - use wasmer::Value; - let lhs_ptr: usize = 0; let result_ptr: usize = lhs_ptr + FIELD_BYTES; self.transfer_to_heap(&input.to_be_bytes(), lhs_ptr); self.call_multiple( "compute_public_key", - vec![&Value::I32(lhs_ptr as i32), &Value::I32(result_ptr as i32)], + vec![&lhs_ptr.into(), &result_ptr.into()], ); let result_bytes = self.slice_memory(result_ptr, 2 * FIELD_BYTES); diff --git a/src/schnorr.rs b/src/schnorr.rs index 702309c6..c4aaa8fd 100644 --- a/src/schnorr.rs +++ b/src/schnorr.rs @@ -36,7 +36,6 @@ impl SchnorrSig for Barretenberg { impl SchnorrSig for Barretenberg { fn construct_signature(&self, message: &[u8], private_key: [u8; 32]) -> [u8; 64] { use super::{wasm::WASM_SCRATCH_BYTES, FIELD_BYTES}; - use wasmer::Value; let sig_s_ptr: usize = 0; let sig_e_ptr: usize = sig_s_ptr + FIELD_BYTES; @@ -52,11 +51,11 @@ impl SchnorrSig for Barretenberg { self.call_multiple( "construct_signature", vec![ - &Value::I32(message_ptr as i32), - &Value::I32(message.len() as i32), - &Value::I32(private_key_ptr as i32), - &Value::I32(sig_s_ptr as i32), - &Value::I32(sig_e_ptr as i32), + &message_ptr.into(), + &message.len().into(), + &private_key_ptr.into(), + &sig_s_ptr.into(), + &sig_e_ptr.into(), ], ); @@ -72,7 +71,6 @@ impl SchnorrSig for Barretenberg { #[allow(dead_code)] fn construct_public_key(&self, private_key: [u8; 32]) -> [u8; 64] { use super::FIELD_BYTES; - use wasmer::Value; let private_key_ptr: usize = 0; let result_ptr: usize = private_key_ptr + FIELD_BYTES; @@ -81,10 +79,7 @@ impl SchnorrSig for Barretenberg { self.call_multiple( "compute_public_key", - vec![ - &Value::I32(private_key_ptr as i32), - &Value::I32(result_ptr as i32), - ], + vec![&private_key_ptr.into(), &result_ptr.into()], ); self.slice_memory(result_ptr, 2 * FIELD_BYTES) @@ -94,7 +89,6 @@ impl SchnorrSig for Barretenberg { fn verify_signature(&self, pub_key: [u8; 64], sig: [u8; 64], message: &[u8]) -> bool { use super::{wasm::WASM_SCRATCH_BYTES, FIELD_BYTES}; - use wasmer::Value; let (sig_s, sig_e) = sig.split_at(FIELD_BYTES); @@ -115,19 +109,15 @@ impl SchnorrSig for Barretenberg { let wasm_value = self.call_multiple( "verify_signature", vec![ - &Value::I32(message_ptr as i32), - &Value::I32(message.len() as i32), - &Value::I32(public_key_ptr as i32), - &Value::I32(sig_s_ptr as i32), - &Value::I32(sig_e_ptr as i32), + &message_ptr.into(), + &message.len().into(), + &public_key_ptr.into(), + &sig_s_ptr.into(), + &sig_e_ptr.into(), ], ); - match wasm_value.into_i32() { - 0 => false, - 1 => true, - _=> unreachable!("verify signature should return a boolean to indicate whether the signature + parameters were valid") - } + wasm_value.bool() // Note, currently for Barretenberg plonk, if the signature fails // then the whole circuit fails. }