diff --git a/.aztec-sync-commit b/.aztec-sync-commit index 82e81e9d74c..fdbc14d511e 100644 --- a/.aztec-sync-commit +++ b/.aztec-sync-commit @@ -1 +1 @@ -221e2479622aef8e70120dc0a9f91ffcbc99efba +1d785fd1087d7387fc29213ca3be50b2fc9c4725 diff --git a/acvm-repo/acvm_js/src/execute.rs b/acvm-repo/acvm_js/src/execute.rs index 9f2b07b31fc..fd1e464efa8 100644 --- a/acvm-repo/acvm_js/src/execute.rs +++ b/acvm-repo/acvm_js/src/execute.rs @@ -19,20 +19,6 @@ use crate::{ JsExecutionError, JsSolvedAndReturnWitness, JsWitnessMap, JsWitnessStack, }; -#[wasm_bindgen] -pub struct WasmBlackBoxFunctionSolver; - -impl WasmBlackBoxFunctionSolver { - async fn initialize() -> WasmBlackBoxFunctionSolver { - WasmBlackBoxFunctionSolver - } -} - -#[wasm_bindgen(js_name = "createBlackBoxSolver")] -pub async fn create_black_box_solver() -> WasmBlackBoxFunctionSolver { - WasmBlackBoxFunctionSolver::initialize().await -} - /// Executes an ACIR circuit to generate the solved witness from the initial witness. /// /// @param {Uint8Array} circuit - A serialized representation of an ACIR circuit @@ -58,14 +44,12 @@ pub async fn execute_circuit( /// Executes an ACIR circuit to generate the solved witness from the initial witness. /// This method also extracts the public return values from the solved witness into its own return witness. /// -/// @param {&WasmBlackBoxFunctionSolver} solver - A black box solver. /// @param {Uint8Array} circuit - A serialized representation of an ACIR circuit /// @param {WitnessMap} initial_witness - The initial witness map defining all of the inputs to `circuit`.. /// @param {ForeignCallHandler} foreign_call_handler - A callback to process any foreign calls from the circuit. /// @returns {SolvedAndReturnWitness} The solved witness calculated by executing the circuit on the provided inputs, as well as the return witness indices as specified by the circuit. #[wasm_bindgen(js_name = executeCircuitWithReturnWitness, skip_jsdoc)] pub async fn execute_circuit_with_return_witness( - _solver: &WasmBlackBoxFunctionSolver, program: Vec, initial_witness: JsWitnessMap, foreign_call_handler: ForeignCallHandler, @@ -94,28 +78,10 @@ pub async fn execute_circuit_with_return_witness( /// Executes an ACIR circuit to generate the solved witness from the initial witness. /// -/// @param {&WasmBlackBoxFunctionSolver} solver - A black box solver. -/// @param {Uint8Array} circuit - A serialized representation of an ACIR circuit -/// @param {WitnessMap} initial_witness - The initial witness map defining all of the inputs to `circuit`.. -/// @param {ForeignCallHandler} foreign_call_handler - A callback to process any foreign calls from the circuit. -/// @returns {WitnessMap} The solved witness calculated by executing the circuit on the provided inputs. -#[wasm_bindgen(js_name = executeCircuitWithBlackBoxSolver, skip_jsdoc)] -pub async fn execute_circuit_with_black_box_solver( - _solver: &WasmBlackBoxFunctionSolver, - program: Vec, - initial_witness: JsWitnessMap, - foreign_call_handler: ForeignCallHandler, -) -> Result { - console_error_panic_hook::set_once(); - - let mut witness_stack = - execute_program_with_native_type_return(program, initial_witness, &foreign_call_handler) - .await?; - let witness_map = - witness_stack.pop().expect("Should have at least one witness on the stack").witness; - Ok(witness_map.into()) -} - +/// @param {Uint8Array} program - A serialized representation of an ACIR program +/// @param {WitnessMap} initial_witness - The initial witness map defining all of the inputs to `program`. +/// @param {ForeignCallHandler} foreign_call_handler - A callback to process any foreign calls from the program. +/// @returns {WitnessStack} The solved witness calculated by executing the program on the provided inputs. #[wasm_bindgen(js_name = executeProgram, skip_jsdoc)] pub async fn execute_program( program: Vec, @@ -124,21 +90,8 @@ pub async fn execute_program( ) -> Result { console_error_panic_hook::set_once(); - let solver = WasmBlackBoxFunctionSolver::initialize().await; - - execute_program_with_black_box_solver(&solver, program, initial_witness, &foreign_call_handler) - .await -} - -#[wasm_bindgen(js_name = executeProgramWithBlackBoxSolver, skip_jsdoc)] -pub async fn execute_program_with_black_box_solver( - _solver: &WasmBlackBoxFunctionSolver, - program: Vec, - initial_witness: JsWitnessMap, - foreign_call_executor: &ForeignCallHandler, -) -> Result { let witness_stack = - execute_program_with_native_type_return(program, initial_witness, foreign_call_executor) + execute_program_with_native_type_return(program, initial_witness, &foreign_call_handler) .await?; Ok(witness_stack.into()) diff --git a/acvm-repo/acvm_js/src/lib.rs b/acvm-repo/acvm_js/src/lib.rs index 3b8210f4875..fdb8d5ffe08 100644 --- a/acvm-repo/acvm_js/src/lib.rs +++ b/acvm-repo/acvm_js/src/lib.rs @@ -23,10 +23,7 @@ pub use build_info::build_info; pub use compression::{ compress_witness, compress_witness_stack, decompress_witness, decompress_witness_stack, }; -pub use execute::{ - create_black_box_solver, execute_circuit, execute_circuit_with_black_box_solver, - execute_circuit_with_return_witness, execute_program, execute_program_with_black_box_solver, -}; +pub use execute::{execute_circuit, execute_circuit_with_return_witness, execute_program}; pub use js_execution_error::JsExecutionError; pub use js_witness_map::JsSolvedAndReturnWitness; pub use js_witness_map::JsWitnessMap; diff --git a/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts b/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts index 625cc91cfe9..cfd5523b79f 100644 --- a/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts +++ b/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts @@ -1,13 +1,5 @@ import { expect } from '@esm-bundle/chai'; -import initACVM, { - createBlackBoxSolver, - executeCircuit, - executeCircuitWithBlackBoxSolver, - WasmBlackBoxFunctionSolver, - WitnessMap, - initLogLevel, - ForeignCallHandler, -} from '@noir-lang/acvm_js'; +import initACVM, { executeCircuit, WitnessMap, initLogLevel, ForeignCallHandler } from '@noir-lang/acvm_js'; beforeEach(async () => { await initACVM(); @@ -122,23 +114,3 @@ it('successfully executes a MemoryOp opcode', async () => { expect(solvedWitness).to.be.deep.eq(expectedWitnessMap); }); - -it('successfully executes two circuits with same backend', async function () { - // chose pedersen op here because it is the one with slow initialization - // that led to the decision to pull backend initialization into a separate - // function/wasmbind - const solver: WasmBlackBoxFunctionSolver = await createBlackBoxSolver(); - - const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/pedersen'); - - const solvedWitness0: WitnessMap = await executeCircuitWithBlackBoxSolver(solver, bytecode, initialWitnessMap, () => { - throw Error('unexpected oracle'); - }); - - expect(solvedWitness0).to.be.deep.eq(expectedWitnessMap); - - const solvedWitness1: WitnessMap = await executeCircuitWithBlackBoxSolver(solver, bytecode, initialWitnessMap, () => { - throw Error('unexpected oracle'); - }); - expect(solvedWitness1).to.be.deep.eq(expectedWitnessMap); -}); diff --git a/acvm-repo/acvm_js/test/node/execute_circuit.test.ts b/acvm-repo/acvm_js/test/node/execute_circuit.test.ts index 3f9bde2898e..1e3517e8814 100644 --- a/acvm-repo/acvm_js/test/node/execute_circuit.test.ts +++ b/acvm-repo/acvm_js/test/node/execute_circuit.test.ts @@ -1,9 +1,6 @@ import { expect } from 'chai'; import { - createBlackBoxSolver, executeCircuit, - executeCircuitWithBlackBoxSolver, - WasmBlackBoxFunctionSolver, WitnessMap, ForeignCallHandler, executeProgram, @@ -120,40 +117,18 @@ it('successfully executes a MemoryOp opcode', async () => { expect(solvedWitness).to.be.deep.eq(expectedWitnessMap); }); -it('successfully executes two circuits with same backend', async function () { - this.timeout(10000); - - // chose pedersen op here because it is the one with slow initialization - // that led to the decision to pull backend initialization into a separate - // function/wasmbind - const solver: WasmBlackBoxFunctionSolver = await createBlackBoxSolver(); - - const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/pedersen'); - - const solvedWitness0 = await executeCircuitWithBlackBoxSolver(solver, bytecode, initialWitnessMap, () => { - throw Error('unexpected oracle'); - }); - - const solvedWitness1 = await executeCircuitWithBlackBoxSolver(solver, bytecode, initialWitnessMap, () => { - throw Error('unexpected oracle'); - }); - - expect(solvedWitness0).to.be.deep.eq(expectedWitnessMap); - expect(solvedWitness1).to.be.deep.eq(expectedWitnessMap); -}); - -it('successfully executes 500 circuits with same backend', async function () { +it('successfully executes 500 pedersen circuits', async function () { this.timeout(100000); - // chose pedersen op here because it is the one with slow initialization - // that led to the decision to pull backend initialization into a separate - // function/wasmbind - const solver: WasmBlackBoxFunctionSolver = await createBlackBoxSolver(); + // Pedersen opcodes used to have a large upfront cost due to generator calculation + // so we'd need to pass around the blackbox solver in JS to avoid redoing this work. + // + // This test now shows that we don't need to do this anymore without a performance regression. const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/pedersen'); for (let i = 0; i < 500; i++) { - const solvedWitness = await executeCircuitWithBlackBoxSolver(solver, bytecode, initialWitnessMap, () => { + const solvedWitness = await executeCircuit(bytecode, initialWitnessMap, () => { throw Error('unexpected oracle'); }); diff --git a/aztec_macros/src/lib.rs b/aztec_macros/src/lib.rs index 5326920511b..2daf86dc643 100644 --- a/aztec_macros/src/lib.rs +++ b/aztec_macros/src/lib.rs @@ -134,7 +134,6 @@ fn transform_module( for func in module.functions.iter_mut() { let mut is_private = false; let mut is_public = false; - let mut is_public_vm = false; let mut is_initializer = false; let mut is_internal = false; let mut insert_init_check = has_initializer; @@ -152,8 +151,6 @@ fn transform_module( is_internal = true; } else if is_custom_attribute(&secondary_attribute, "aztec(public)") { is_public = true; - } else if is_custom_attribute(&secondary_attribute, "aztec(public-vm)") { - is_public_vm = true; } if is_custom_attribute(&secondary_attribute, "aztec(view)") { is_static = true; @@ -161,14 +158,8 @@ fn transform_module( } // Apply transformations to the function based on collected attributes - if is_private || is_public || is_public_vm { - let fn_type = if is_private { - "Private" - } else if is_public_vm { - "Avm" - } else { - "Public" - }; + if is_private || is_public { + let fn_type = if is_private { "Private" } else { "Public" }; let stub_src = stub_function(fn_type, func, is_static); stubs.push((stub_src, Location { file: *file_id, span: func.name_ident().span() })); diff --git a/aztec_macros/src/transforms/contract_interface.rs b/aztec_macros/src/transforms/contract_interface.rs index bb63357d251..90f9ce6164a 100644 --- a/aztec_macros/src/transforms/contract_interface.rs +++ b/aztec_macros/src/transforms/contract_interface.rs @@ -88,7 +88,7 @@ pub fn stub_function(aztec_visibility: &str, func: &NoirFunction, is_static_call }) .collect::>() .join(""); - if aztec_visibility != "Avm" { + if aztec_visibility != "Public" { let args_hash = if !parameters.is_empty() { format!( "let mut args_acc: [Field] = &[]; @@ -125,7 +125,7 @@ pub fn stub_function(aztec_visibility: &str, func: &NoirFunction, is_static_call ); let fn_body = format!( "{} - dep::aztec::context::Avm{}{}CallInterface {{ + dep::aztec::context::Public{}{}CallInterface {{ target_contract: self.target_contract, selector: {}, args: args_acc, @@ -134,7 +134,7 @@ pub fn stub_function(aztec_visibility: &str, func: &NoirFunction, is_static_call args, is_static, is_void, fn_selector, ); format!( - "pub fn {}(self, {}) -> dep::aztec::context::Avm{}{}CallInterface{} {{ + "pub fn {}(self, {}) -> dep::aztec::context::Public{}{}CallInterface{} {{ {} }}", fn_name, fn_parameters, is_static, is_void, return_type_hint, fn_body diff --git a/aztec_macros/src/transforms/functions.rs b/aztec_macros/src/transforms/functions.rs index 00e9c444421..0fb13975fec 100644 --- a/aztec_macros/src/transforms/functions.rs +++ b/aztec_macros/src/transforms/functions.rs @@ -36,15 +36,15 @@ pub fn transform_function( is_internal: bool, is_static: bool, ) -> Result<(), AztecMacroError> { + assert!(matches!(ty, "Private" | "Public")); let context_name = format!("{}Context", ty); let inputs_name = format!("{}ContextInputs", ty); let return_type_name = format!("{}CircuitPublicInputs", ty); - let is_avm = ty == "Avm"; let is_private = ty == "Private"; // Force a static context if the function is static if is_static { - let is_static_check = create_static_check(func.name(), is_avm); + let is_static_check = create_static_check(func.name(), is_private); func.def.body.statements.insert(0, is_static_check); } @@ -72,10 +72,10 @@ pub fn transform_function( } // Insert the context creation as the first action - let create_context = if !is_avm { - create_context(&context_name, &func.def.parameters)? + let create_context = if is_private { + create_context_private(&context_name, &func.def.parameters)? } else { - create_context_avm()? + create_context_public()? }; func.def.body.statements.splice(0..0, (create_context).iter().cloned()); @@ -84,7 +84,7 @@ pub fn transform_function( func.def.parameters.insert(0, input); // Abstract return types such that they get added to the kernel's return_values - if !is_avm { + if is_private { if let Some(return_values_statements) = abstract_return_values(func)? { // In case we are pushing return values to the context, we remove the statement that originated it // This avoids running duplicate code, since blocks like if/else can be value returning statements @@ -101,13 +101,13 @@ pub fn transform_function( } // Push the finish method call to the end of the function - if !is_avm { + if is_private { let finish_def = create_context_finish(); func.def.body.statements.push(finish_def); } // The AVM doesn't need a return type yet. - if !is_avm { + if is_private { let return_type = create_return_type(&return_type_name); func.def.return_type = return_type; func.def.return_visibility = Visibility::Public; @@ -116,7 +116,7 @@ pub fn transform_function( } // Public functions should have unconstrained auto-inferred - func.def.is_unconstrained = matches!(ty, "Public" | "Avm"); + func.def.is_unconstrained = !is_private; // Private functions need to be recursive if is_private { @@ -285,8 +285,8 @@ fn create_mark_as_initialized(ty: &str) -> Statement { /// ```noir /// assert(context.inputs.call_context.is_static_call == true, "Function can only be called statically") /// ``` -fn create_static_check(fname: &str, is_avm: bool) -> Statement { - let is_static_call_expr = if !is_avm { +fn create_static_check(fname: &str, is_private: bool) -> Statement { + let is_static_call_expr = if is_private { ["inputs", "call_context", "is_static_call"] .iter() .fold(variable("context"), |acc, member| member_access(acc, member)) @@ -410,7 +410,7 @@ fn serialize_to_hasher( /// let mut context = PrivateContext::new(inputs, hasher.hash()); /// } /// ``` -fn create_context(ty: &str, params: &[Param]) -> Result, AztecMacroError> { +fn create_context_private(ty: &str, params: &[Param]) -> Result, AztecMacroError> { let mut injected_statements: Vec = vec![]; let hasher_name = "args_hasher"; @@ -471,30 +471,33 @@ fn create_context(ty: &str, params: &[Param]) -> Result, AztecMac Ok(injected_statements) } -/// Creates the private context object to be accessed within the function, the parameters need to be extracted to be -/// appended into the args hash object. +/// Creates the public context object to be accessed within the function. /// /// The replaced code: /// ```noir -/// #[aztec(public-vm)] -/// fn foo(inputs: AvmContextInputs, ...) -> Field { -/// let mut context = AvmContext::new(inputs); +/// #[aztec(public)] +/// fn foo(inputs: PublicContextInputs, ...) -> Field { +/// let mut context = PublicContext::new(inputs); /// } /// ``` -fn create_context_avm() -> Result, AztecMacroError> { +fn create_context_public() -> Result, AztecMacroError> { let mut injected_expressions: Vec = vec![]; // Create the inputs to the context - let ty = "AvmContext"; let inputs_expression = variable("inputs"); - let path_snippet = ty.to_case(Case::Snake); // e.g. private_context // let mut context = {ty}::new(inputs, hash); let let_context = mutable_assignment( "context", // Assigned to call( - variable_path(chained_dep!("aztec", "context", &path_snippet, ty, "new")), // Path - vec![inputs_expression], // args + variable_path(chained_dep!( + "aztec", + "context", + "public_context", + "PublicContext", + "new" + )), // Path + vec![inputs_expression], // args ), ); injected_expressions.push(let_context); diff --git a/aztec_macros/src/transforms/note_interface.rs b/aztec_macros/src/transforms/note_interface.rs index f183c69b27a..fdce8b81db2 100644 --- a/aztec_macros/src/transforms/note_interface.rs +++ b/aztec_macros/src/transforms/note_interface.rs @@ -76,19 +76,27 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt // Identify the note type (struct name), its fields and its serialized length (generic param of NoteInterface trait impl) let note_type = note_struct.name.0.contents.to_string(); let mut note_fields = vec![]; - let note_serialized_len = match &trait_impl.trait_generics[0].typ { - UnresolvedTypeData::Named(path, _, _) => Ok(path.last_segment().0.contents.to_string()), - UnresolvedTypeData::Expression(UnresolvedTypeExpression::Constant(val, _)) => { - Ok(val.to_string()) - } - _ => Err(AztecMacroError::CouldNotImplementNoteInterface { - span: trait_impl.object_type.span, - secondary_message: Some(format!( - "Cannot find note serialization length for: {}", - note_type - )), - }), - }?; + let note_interface_generics = trait_impl + .trait_generics + .iter() + .map(|gen| match gen.typ.clone() { + UnresolvedTypeData::Named(path, _, _) => { + Ok(path.last_segment().0.contents.to_string()) + } + UnresolvedTypeData::Expression(UnresolvedTypeExpression::Constant(val, _)) => { + Ok(val.to_string()) + } + _ => Err(AztecMacroError::CouldNotImplementNoteInterface { + span: trait_impl.object_type.span, + secondary_message: Some(format!( + "NoteInterface must be generic over NOTE_LEN and NOTE_BYTES_LEN: {}", + note_type + )), + }), + }) + .collect::, _>>()?; + let [note_serialized_len, note_bytes_len]: [_; 2] = + note_interface_generics.try_into().unwrap(); let note_type_id = note_type_id(¬e_type); // Automatically inject the header field if it's not present @@ -186,12 +194,73 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt generate_compute_note_content_hash(¬e_type, note_interface_impl_span)?; trait_impl.items.push(TraitImplItem::Function(get_header_fn)); } + + if !check_trait_method_implemented(trait_impl, "to_be_bytes") { + let get_header_fn = generate_note_to_be_bytes( + ¬e_type, + note_bytes_len.as_str(), + note_serialized_len.as_str(), + note_interface_impl_span, + )?; + trait_impl.items.push(TraitImplItem::Function(get_header_fn)); + } } module.types.extend(structs_to_inject); Ok(()) } +fn generate_note_to_be_bytes( + note_type: &String, + byte_length: &str, + serialized_length: &str, + impl_span: Option, +) -> Result { + let function_source = format!( + " + fn to_be_bytes(self: {1}, storage_slot: Field) -> [u8; {0}] {{ + assert({0} == {2} * 32 + 64, \"Note byte length must be equal to (serialized_length * 32) + 64 bytes\"); + let serialized_note = self.serialize_content(); + + let mut buffer: [u8; {0}] = [0; {0}]; + + let storage_slot_bytes = storage_slot.to_be_bytes(32); + let note_type_id_bytes = {1}::get_note_type_id().to_be_bytes(32); + + for i in 0..32 {{ + buffer[i] = storage_slot_bytes[i]; + buffer[32 + i] = note_type_id_bytes[i]; + }} + + for i in 0..serialized_note.len() {{ + let bytes = serialized_note[i].to_be_bytes(32); + for j in 0..32 {{ + buffer[64 + i * 32 + j] = bytes[j]; + }} + }} + buffer + }} + ", + byte_length, note_type, serialized_length + ) + .to_string(); + + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementNoteInterface { + secondary_message: Some("Failed to parse Noir macro code (fn to_be_bytes). This is either a bug in the compiler or the Noir macro code".to_string()), + span: impl_span + }); + } + + let mut function_ast = function_ast.into_sorted(); + let mut noir_fn = function_ast.functions.remove(0); + noir_fn.def.span = impl_span.unwrap(); + noir_fn.def.visibility = ItemVisibility::Public; + Ok(noir_fn) +} + fn generate_note_get_header( note_type: &String, note_header_field_name: &String, @@ -209,6 +278,7 @@ fn generate_note_get_header( let (function_ast, errors) = parse_program(&function_source); if !errors.is_empty() { + dbg!(errors); return Err(AztecMacroError::CouldNotImplementNoteInterface { secondary_message: Some("Failed to parse Noir macro code (fn get_header). This is either a bug in the compiler or the Noir macro code".to_string()), span: impl_span diff --git a/aztec_macros/src/utils/hir_utils.rs b/aztec_macros/src/utils/hir_utils.rs index 99b02acd606..3e92217ee9c 100644 --- a/aztec_macros/src/utils/hir_utils.rs +++ b/aztec_macros/src/utils/hir_utils.rs @@ -324,7 +324,7 @@ pub fn get_serialized_length( .iter() .find_map(|&trait_id| { let r#trait = interner.get_trait(trait_id); - if r#trait.name.0.contents == trait_name && r#trait.generics.len() == 1 { + if r#trait.name.0.contents == trait_name { interner.lookup_all_trait_implementations(typ, trait_id).into_iter().next() } else { None diff --git a/compiler/integration-tests/test/browser/recursion.test.ts b/compiler/integration-tests/test/browser/recursion.test.ts index a8927aa6a75..abbee7b96ad 100644 --- a/compiler/integration-tests/test/browser/recursion.test.ts +++ b/compiler/integration-tests/test/browser/recursion.test.ts @@ -40,7 +40,8 @@ describe('It compiles noir program code, receiving circuit bytes and abi object. circuit_main_toml = await new Response(await getFile(`${base_relative_path}/${circuit_main}/Prover.toml`)).text(); }); - it('Should generate valid inner proof for correct input, then verify proof within a proof', async () => { + // TODO(https://github.com/noir-lang/noir/issues/5106): Reinstate this test. + it.skip('Should generate valid inner proof for correct input, then verify proof within a proof', async () => { const main_program = await getCircuit(`${base_relative_path}/${circuit_main}`); const main_inputs: InputMap = TOML.parse(circuit_main_toml) as InputMap; diff --git a/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts b/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts index 6147f770f16..ca7f19309d6 100644 --- a/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts +++ b/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts @@ -11,7 +11,8 @@ import { Field, InputMap } from '@noir-lang/noirc_abi'; import { compile, createFileManager } from '@noir-lang/noir_wasm'; -it(`smart contract can verify a recursive proof`, async () => { +// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6672): Reinstate this test. +it.skip(`smart contract can verify a recursive proof`, async () => { const basePath = resolve(join(__dirname, '../../../../')); const fm = createFileManager(basePath); const innerCompilationResult = await compile( diff --git a/noir_stdlib/src/aes128.nr b/noir_stdlib/src/aes128.nr index cd61021a953..e6e2a5e4997 100644 --- a/noir_stdlib/src/aes128.nr +++ b/noir_stdlib/src/aes128.nr @@ -2,6 +2,3 @@ // docs:start:aes128 pub fn aes128_encrypt(input: [u8; N], iv: [u8; 16], key: [u8; 16]) -> [u8] {} // docs:end:aes128 - -#[foreign(aes128_encrypt)] -pub fn aes128_encrypt_slice(input: [u8], iv: [u8; 16], key: [u8; 16]) -> [u8] {} diff --git a/test_programs/execution_success/ecdsa_secp256r1_3x/Nargo.toml b/test_programs/execution_success/ecdsa_secp256r1_3x/Nargo.toml new file mode 100644 index 00000000000..860b863a365 --- /dev/null +++ b/test_programs/execution_success/ecdsa_secp256r1_3x/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "ecdsa_secp256r1_3x" +description = "Three ECDSA secp256r1 verifications" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/ecdsa_secp256r1_3x/Prover.toml b/test_programs/execution_success/ecdsa_secp256r1_3x/Prover.toml new file mode 100644 index 00000000000..e8edf26b2f3 --- /dev/null +++ b/test_programs/execution_success/ecdsa_secp256r1_3x/Prover.toml @@ -0,0 +1,57 @@ +hashed_message = [ + 84, 112, 91, 163, 186, 175, 219, 223, 186, 140, 95, 154, 112, 247, 168, 155, 238, 152, + 217, 6, 181, 62, 49, 7, 77, 167, 186, 236, 220, 13, 169, 173, +] +pub_key_x = [ + 85, 15, 71, 16, 3, 243, 223, 151, 195, 223, 80, 106, 199, 151, 246, 114, 31, 177, 161, + 251, 123, 143, 111, 131, 210, 36, 73, 138, 101, 200, 142, 36, +] +pub_key_y = [ + 19, 96, 147, 215, 1, 46, 80, 154, 115, 113, 92, 189, 11, 0, 163, 204, 15, 244, 181, + 192, 27, 63, 250, 25, 106, 177, 251, 50, 112, 54, 184, 230, +] +signature = [ + 44, 112, 168, 208, 132, 182, 43, 252, 92, 224, 54, 65, 202, 249, 247, 42, + 212, 218, 140, 129, 191, 230, 236, 148, 135, 187, 94, 27, 239, 98, 161, 50, + 24, 173, 158, 226, 158, 175, 53, 31, 220, 80, 241, 82, 12, 66, 94, 155, + 144, 138, 7, 39, 139, 67, 176, 236, 123, 135, 39, 120, 193, 78, 7, 132 +] + +hashed_message_2 = [ + 84, 112, 91, 163, 186, 175, 219, 223, 186, 140, 95, 154, 112, 247, 168, 155, 238, 152, + 217, 6, 181, 62, 49, 7, 77, 167, 186, 236, 220, 13, 169, 173, +] +pub_key_x_2 = [ + 85, 15, 71, 16, 3, 243, 223, 151, 195, 223, 80, 106, 199, 151, 246, 114, 31, 177, 161, + 251, 123, 143, 111, 131, 210, 36, 73, 138, 101, 200, 142, 36, +] +pub_key_y_2 = [ + 19, 96, 147, 215, 1, 46, 80, 154, 115, 113, 92, 189, 11, 0, 163, 204, 15, 244, 181, + 192, 27, 63, 250, 25, 106, 177, 251, 50, 112, 54, 184, 230, +] +signature_2 = [ + 44, 112, 168, 208, 132, 182, 43, 252, 92, 224, 54, 65, 202, 249, 247, 42, + 212, 218, 140, 129, 191, 230, 236, 148, 135, 187, 94, 27, 239, 98, 161, 50, + 24, 173, 158, 226, 158, 175, 53, 31, 220, 80, 241, 82, 12, 66, 94, 155, + 144, 138, 7, 39, 139, 67, 176, 236, 123, 135, 39, 120, 193, 78, 7, 132 +] + + +hashed_message_3 = [ + 84, 112, 91, 163, 186, 175, 219, 223, 186, 140, 95, 154, 112, 247, 168, 155, 238, 152, + 217, 6, 181, 62, 49, 7, 77, 167, 186, 236, 220, 13, 169, 173, +] +pub_key_x_3 = [ + 85, 15, 71, 16, 3, 243, 223, 151, 195, 223, 80, 106, 199, 151, 246, 114, 31, 177, 161, + 251, 123, 143, 111, 131, 210, 36, 73, 138, 101, 200, 142, 36, +] +pub_key_y_3 = [ + 19, 96, 147, 215, 1, 46, 80, 154, 115, 113, 92, 189, 11, 0, 163, 204, 15, 244, 181, + 192, 27, 63, 250, 25, 106, 177, 251, 50, 112, 54, 184, 230, +] +signature_3 = [ + 44, 112, 168, 208, 132, 182, 43, 252, 92, 224, 54, 65, 202, 249, 247, 42, + 212, 218, 140, 129, 191, 230, 236, 148, 135, 187, 94, 27, 239, 98, 161, 50, + 24, 173, 158, 226, 158, 175, 53, 31, 220, 80, 241, 82, 12, 66, 94, 155, + 144, 138, 7, 39, 139, 67, 176, 236, 123, 135, 39, 120, 193, 78, 7, 132 +] \ No newline at end of file diff --git a/test_programs/execution_success/ecdsa_secp256r1_3x/src/main.nr b/test_programs/execution_success/ecdsa_secp256r1_3x/src/main.nr new file mode 100644 index 00000000000..e7a6be9d47a --- /dev/null +++ b/test_programs/execution_success/ecdsa_secp256r1_3x/src/main.nr @@ -0,0 +1,23 @@ +use dep::std; + +fn main( + hashed_message: [u8; 32], + pub_key_x: [u8; 32], + pub_key_y: [u8; 32], + signature: [u8; 64], + hashed_message_2: [u8; 32], + pub_key_x_2: [u8; 32], + pub_key_y_2: [u8; 32], + signature_2: [u8; 64], + hashed_message_3: [u8; 32], + pub_key_x_3: [u8; 32], + pub_key_y_3: [u8; 32], + signature_3: [u8; 64] +) { + let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + assert(valid_signature); + let valid_signature_2 = std::ecdsa_secp256r1::verify_signature(pub_key_x_2, pub_key_y_2, signature_2, hashed_message_2); + assert(valid_signature_2); + let valid_signature_3 = std::ecdsa_secp256r1::verify_signature(pub_key_x_3, pub_key_y_3, signature_3, hashed_message_3); + assert(valid_signature_3); +} diff --git a/tooling/noir_js/src/witness_generation.ts b/tooling/noir_js/src/witness_generation.ts index 7d018c81d53..c84cb2e83b3 100644 --- a/tooling/noir_js/src/witness_generation.ts +++ b/tooling/noir_js/src/witness_generation.ts @@ -1,25 +1,8 @@ import { abiDecodeError, abiEncode, InputMap } from '@noir-lang/noirc_abi'; import { base64Decode } from './base64_decode.js'; -import { - WitnessStack, - ForeignCallHandler, - ForeignCallInput, - createBlackBoxSolver, - WasmBlackBoxFunctionSolver, - executeProgramWithBlackBoxSolver, - ExecutionError, -} from '@noir-lang/acvm_js'; +import { WitnessStack, ForeignCallHandler, ForeignCallInput, ExecutionError, executeProgram } from '@noir-lang/acvm_js'; import { Abi, CompiledCircuit } from '@noir-lang/types'; -let solver: Promise; - -const getSolver = (): Promise => { - if (!solver) { - solver = createBlackBoxSolver(); - } - return solver; -}; - const defaultForeignCallHandler: ForeignCallHandler = async (name: string, args: ForeignCallInput[]) => { if (name == 'print') { // By default we do not print anything for `print` foreign calls due to a need for formatting, @@ -70,12 +53,7 @@ export async function generateWitness( // Execute the circuit to generate the rest of the witnesses and serialize // them into a Uint8Array. try { - const solvedWitness = await executeProgramWithBlackBoxSolver( - await getSolver(), - base64Decode(compiledProgram.bytecode), - witnessMap, - foreignCallHandler, - ); + const solvedWitness = await executeProgram(base64Decode(compiledProgram.bytecode), witnessMap, foreignCallHandler); return solvedWitness; } catch (err) { // Typescript types catched errors as unknown or any, so we need to narrow its type to check if it has raw assertion payload.