From 2d43c0d62c086944f3c93006c65716f24d1b4705 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Mon, 19 Jun 2023 19:57:06 +0700 Subject: [PATCH] chore: run browser tests on both Chromium and Webkit (#41) --------- Co-authored-by: Koby --- .github/workflows/test.yml | 4 +- cspell.json | 2 + src/barretenberg/mod.rs | 55 +++++++++++++++------------- src/barretenberg/pedersen.rs | 19 ---------- src/barretenberg/scalar_mul.rs | 18 --------- src/barretenberg/schnorr.rs | 53 --------------------------- src/execute.rs | 10 ++++- test/browser/execute_circuit.test.ts | 6 ++- web-test-runner.config.mjs | 8 +++- 9 files changed, 54 insertions(+), 121 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 31b8b3b4c..5266493ee 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -78,7 +78,9 @@ jobs: uses: ./.github/actions/setup - name: Install playwright deps - run: npx playwright install --with-deps webkit + run: | + npx playwright install + npx playwright install-deps - name: Run browser tests run: yarn test:browser diff --git a/cspell.json b/cspell.json index 7a549d9ba..8467494cd 100644 --- a/cspell.json +++ b/cspell.json @@ -5,6 +5,7 @@ // "blackbox", "bindir", + "brillig", "cout", "jsdoc", "keccak", @@ -23,6 +24,7 @@ "ESUCCESS", "fdstat", "getrandom", + "jsvalue", "logstr", "plookup", "wasi", diff --git a/src/barretenberg/mod.rs b/src/barretenberg/mod.rs index c4f66e0ab..efae7ad06 100644 --- a/src/barretenberg/mod.rs +++ b/src/barretenberg/mod.rs @@ -8,7 +8,6 @@ mod barretenberg_structures; pub(crate) mod pedersen; pub(crate) mod scalar_mul; pub(crate) mod schnorr; - use barretenberg_structures::Assignments; /// The number of bytes necessary to store a `FieldElement`. @@ -54,27 +53,14 @@ pub(crate) struct Barretenberg { instance: wasmer::Instance, } -impl Default for Barretenberg { - fn default() -> Barretenberg { - Barretenberg::new() - } -} - -#[test] -fn smoke() -> Result<(), Error> { - use pedersen::Pedersen; - - let b = Barretenberg::new(); - let (x, y) = b.encrypt(vec![acvm::FieldElement::zero(), acvm::FieldElement::one()])?; - dbg!(x.to_hex(), y.to_hex()); - Ok(()) -} - mod wasm { + use js_sys::WebAssembly::{self}; + use log::debug; use std::cell::RefCell; + use wasmer::{ - imports, Function, FunctionEnv, FunctionEnvMut, Instance, Memory, MemoryType, Module, - Store, Value, WasmPtr, + imports, AsJs, Function, FunctionEnv, FunctionEnvMut, Instance, Memory, MemoryType, Store, + Value, WasmPtr, }; use super::{Barretenberg, Error, FeatureError}; @@ -98,8 +84,8 @@ mod wasm { struct Wasm; impl Barretenberg { - pub(crate) fn new() -> Barretenberg { - let (instance, memory, store) = instance_load(); + pub(crate) async fn new() -> Barretenberg { + let (instance, memory, store) = instance_load().await; Barretenberg { memory, instance, store: RefCell::new(store) } } } @@ -251,16 +237,14 @@ mod wasm { // } } - fn instance_load() -> (Instance, Memory, Store) { + async fn instance_load() -> (Instance, Memory, Store) { + debug!("> Will Load black box functions vendor binary"); let mut store = Store::default(); - let module = Module::new(&store, Wasm::get("barretenberg.wasm").unwrap().data).unwrap(); - let mem_type = MemoryType::new(22, None, false); let memory = Memory::new(&mut store, mem_type).unwrap(); let function_env = FunctionEnv::new(&mut store, memory.clone()); - let custom_imports = imports! { "env" => { "logstr" => Function::new_typed_with_env( @@ -292,7 +276,26 @@ mod wasm { }, }; - (Instance::new(&mut store, &module, &custom_imports).unwrap(), memory, store) + let wasm_binary = Wasm::get("barretenberg.wasm").unwrap().data; + let js_bytes: js_sys::Uint8Array; + unsafe { + js_bytes = js_sys::Uint8Array::view(&wasm_binary); + } + debug!("> Will compile black box functions vendor module"); + let js_module_promise = WebAssembly::compile(&js_bytes); + let js_module: js_sys::WebAssembly::Module = + wasm_bindgen_futures::JsFuture::from(js_module_promise).await.unwrap().into(); + + debug!("> Will create black box functions vendor instance"); + let js_instance_promise = + WebAssembly::instantiate_module(&js_module, &custom_imports.as_jsvalue(&store).into()); + let js_instance = wasm_bindgen_futures::JsFuture::from(js_instance_promise).await.unwrap(); + let module: wasmer::Module = (js_module, wasm_binary).into(); + let instance: wasmer::Instance = Instance::from_jsvalue(&mut store, &module, &js_instance) + .map_err(|_| "Error while creating BlackBox Functions vendor instance") + .unwrap(); + + (instance, memory, store) } fn logstr(mut env: FunctionEnvMut, ptr: i32) { diff --git a/src/barretenberg/pedersen.rs b/src/barretenberg/pedersen.rs index 67a7c0450..47eeb4b85 100644 --- a/src/barretenberg/pedersen.rs +++ b/src/barretenberg/pedersen.rs @@ -23,22 +23,3 @@ impl Pedersen for Barretenberg { Ok((point_x, point_y)) } } - -#[test] -fn pedersen_hash_to_point() -> Result<(), Error> { - let barretenberg = Barretenberg::new(); - let (x, y) = barretenberg.encrypt(vec![FieldElement::zero(), FieldElement::one()])?; - let expected_x = FieldElement::from_hex( - "0x11831f49876c313f2a9ec6d8d521c7ce0b6311c852117e340bfe27fd1ac096ef", - ) - .unwrap(); - let expected_y = FieldElement::from_hex( - "0x0ecf9d98be4597a88c46a7e0fa8836b57a7dcb41ee30f8d8787b11cc259c83fa", - ) - .unwrap(); - - assert_eq!(expected_x.to_hex(), x.to_hex()); - assert_eq!(expected_y.to_hex(), y.to_hex()); - Ok(()) -} -// } diff --git a/src/barretenberg/scalar_mul.rs b/src/barretenberg/scalar_mul.rs index 2a29b7a03..c628e58d7 100644 --- a/src/barretenberg/scalar_mul.rs +++ b/src/barretenberg/scalar_mul.rs @@ -25,21 +25,3 @@ impl ScalarMul for Barretenberg { Ok((pubkey_x, pubkey_y)) } } - -#[cfg(test)] -mod test { - use super::*; - #[test] - fn smoke_test() -> Result<(), Error> { - let barretenberg = Barretenberg::new(); - let input = FieldElement::one(); - - let res = barretenberg.fixed_base(&input)?; - let x = "0000000000000000000000000000000000000000000000000000000000000001"; - let y = "0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c"; - - assert_eq!(x, res.0.to_hex()); - assert_eq!(y, res.1.to_hex()); - Ok(()) - } -} diff --git a/src/barretenberg/schnorr.rs b/src/barretenberg/schnorr.rs index d1e7ec80f..1a6443c57 100644 --- a/src/barretenberg/schnorr.rs +++ b/src/barretenberg/schnorr.rs @@ -102,56 +102,3 @@ impl SchnorrSig for Barretenberg { Ok(verified.try_into()?) } } - -#[test] -fn basic_interop() -> Result<(), Error> { - let barretenberg = Barretenberg::new(); - - // First case should pass, standard procedure for Schnorr - let private_key = [2; 32]; - let message = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - - let public_key = barretenberg.construct_public_key(private_key)?; - let (sig_s, sig_e) = barretenberg.construct_signature(&message, private_key)?; - let valid_signature = barretenberg.verify_signature(public_key, sig_s, sig_e, &message)?; - assert!(valid_signature); - - // Should fail, since the messages are different - let private_key = [2; 32]; - let message = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - - let public_key = barretenberg.construct_public_key(private_key)?; - let (sig_s, sig_e) = barretenberg.construct_signature(&message, private_key)?; - let valid_signature = barretenberg.verify_signature(public_key, sig_s, sig_e, &[0, 2])?; - assert!(!valid_signature); - - // Should fail, since the signature is not valid - let private_key = [2; 32]; - let message = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - let sig_s = [1; 32]; - let sig_e = [1; 32]; - - let public_key = barretenberg.construct_public_key(private_key)?; - let valid_signature = barretenberg.verify_signature(public_key, sig_s, sig_e, &message)?; - assert!(!valid_signature); - - // Should fail, since the public key does not match - let private_key_a = [1; 32]; - let private_key_b = [2; 32]; - let message = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - - let public_key_b = barretenberg.construct_public_key(private_key_b)?; - let (sig_s, sig_e) = barretenberg.construct_signature(&message, private_key_a)?; - let valid_signature = barretenberg.verify_signature(public_key_b, sig_s, sig_e, &message)?; - assert!(!valid_signature); - - // Test the first case again, to check if memory is being freed and overwritten properly - let private_key = [2; 32]; - let message = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - - let public_key = barretenberg.construct_public_key(private_key)?; - let (sig_s, sig_e) = barretenberg.construct_signature(&message, private_key)?; - let valid_signature = barretenberg.verify_signature(public_key, sig_s, sig_e, &message)?; - assert!(valid_signature); - Ok(()) -} diff --git a/src/execute.rs b/src/execute.rs index 2c99c7b90..b7efee91d 100644 --- a/src/execute.rs +++ b/src/execute.rs @@ -19,11 +19,17 @@ use crate::{ JsWitnessMap, }; -#[derive(Default)] struct SimulatedBackend { blackbox_vendor: Barretenberg, } +impl SimulatedBackend { + async fn initialize() -> SimulatedBackend { + let blackbox_vendor = Barretenberg::new().await; + SimulatedBackend { blackbox_vendor } + } +} + impl PartialWitnessGenerator for SimulatedBackend { fn schnorr_verify( &self, @@ -152,7 +158,7 @@ pub async fn execute_circuit( let circuit: Circuit = Circuit::read(&*circuit).expect("Failed to deserialize circuit"); let mut witness_map = WitnessMap::from(initial_witness); - let backend = SimulatedBackend::default(); + let backend = SimulatedBackend::initialize().await; let mut blocks = Blocks::default(); let mut opcodes = circuit.opcodes; diff --git a/test/browser/execute_circuit.test.ts b/test/browser/execute_circuit.test.ts index 5f707fd9a..db4dcbe75 100644 --- a/test/browser/execute_circuit.test.ts +++ b/test/browser/execute_circuit.test.ts @@ -4,10 +4,13 @@ import initACVMSimulator, { abiDecode, executeCircuit, WitnessMap, + init_log_level, } from "../../result/"; beforeEach(async () => { await initACVMSimulator(); + + init_log_level("INFO"); }); it("successfully executes circuit and extracts return value", async () => { @@ -37,7 +40,8 @@ it("successfully executes circuit and extracts return value", async () => { expect(decoded_inputs.return_value).to.equal(expectedResult); }); -it("successfully executes a Pedersen opcode", async () => { +it("successfully executes a Pedersen opcode", async function () { + this.timeout(10000); const { abi, bytecode, inputs, expectedResult } = await import( "../shared/pedersen" ); diff --git a/web-test-runner.config.mjs b/web-test-runner.config.mjs index e353393b8..eb5eb73be 100644 --- a/web-test-runner.config.mjs +++ b/web-test-runner.config.mjs @@ -2,7 +2,13 @@ import { esbuildPlugin } from "@web/dev-server-esbuild"; import { playwrightLauncher } from "@web/test-runner-playwright"; export default { - browsers: [playwrightLauncher({ product: "webkit" })], + browsers: [ + playwrightLauncher({ product: "chromium" }), + playwrightLauncher({ product: "webkit" }), + // Firefox requires 40s to perform a Pedersen hash so we recommend using either + // a Chromium- or Webkit-based browser + // playwrightLauncher({ product: "firefox" }), + ], plugins: [ esbuildPlugin({ ts: true,