diff --git a/avm-transpiler/src/transpile.rs b/avm-transpiler/src/transpile.rs index 0de09a5793c..fda785f1ff9 100644 --- a/avm-transpiler/src/transpile.rs +++ b/avm-transpiler/src/transpile.rs @@ -1,5 +1,4 @@ use acvm::acir::brillig::Opcode as BrilligOpcode; -use acvm::acir::circuit::brillig::Brillig; use acvm::brillig_vm::brillig::{ BinaryFieldOp, BinaryIntOp, BlackBoxOp, HeapArray, HeapVector, MemoryAddress, ValueOrArray, @@ -14,17 +13,17 @@ use crate::opcodes::AvmOpcode; use crate::utils::{dbg_print_avm_program, dbg_print_brillig_program}; /// Transpile a Brillig program to AVM bytecode -pub fn brillig_to_avm(brillig: &Brillig) -> Vec { - dbg_print_brillig_program(brillig); +pub fn brillig_to_avm(brillig_bytecode: &[BrilligOpcode]) -> Vec { + dbg_print_brillig_program(brillig_bytecode); let mut avm_instrs: Vec = Vec::new(); // Map Brillig pcs to AVM pcs // (some Brillig instructions map to >1 AVM instruction) - let brillig_pcs_to_avm_pcs = map_brillig_pcs_to_avm_pcs(avm_instrs.len(), brillig); + let brillig_pcs_to_avm_pcs = map_brillig_pcs_to_avm_pcs(avm_instrs.len(), brillig_bytecode); // Transpile a Brillig instruction to one or more AVM instructions - for brillig_instr in &brillig.bytecode { + for brillig_instr in brillig_bytecode { match brillig_instr { BrilligOpcode::BinaryFieldOp { destination, @@ -1090,12 +1089,15 @@ fn handle_storage_read( /// brillig: the Brillig program /// returns: an array where each index is a Brillig pc, /// and each value is the corresponding AVM pc. -fn map_brillig_pcs_to_avm_pcs(initial_offset: usize, brillig: &Brillig) -> Vec { - let mut pc_map = vec![0; brillig.bytecode.len()]; +fn map_brillig_pcs_to_avm_pcs( + initial_offset: usize, + brillig_bytecode: &[BrilligOpcode], +) -> Vec { + let mut pc_map = vec![0; brillig_bytecode.len()]; pc_map[0] = initial_offset; - for i in 0..brillig.bytecode.len() - 1 { - let num_avm_instrs_for_this_brillig_instr = match &brillig.bytecode[i] { + for i in 0..brillig_bytecode.len() - 1 { + let num_avm_instrs_for_this_brillig_instr = match &brillig_bytecode[i] { BrilligOpcode::Const { bit_size: 254, .. } => 2, _ => 1, }; diff --git a/avm-transpiler/src/transpile_contract.rs b/avm-transpiler/src/transpile_contract.rs index 537dfb34bb3..e28b20aa4a3 100644 --- a/avm-transpiler/src/transpile_contract.rs +++ b/avm-transpiler/src/transpile_contract.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; use acvm::acir::circuit::Program; use crate::transpile::brillig_to_avm; -use crate::utils::extract_brillig_from_acir; +use crate::utils::extract_brillig_from_acir_program; /// Representation of a contract with some transpiled functions #[derive(Debug, Serialize, Deserialize)] @@ -88,10 +88,10 @@ impl From for TranspiledContract { ); // Extract Brillig Opcodes from acir let acir_program = function.bytecode; - let brillig = extract_brillig_from_acir(&acir_program.functions[0].opcodes); + let brillig_bytecode = extract_brillig_from_acir_program(&acir_program); // Transpile to AVM - let avm_bytecode = brillig_to_avm(brillig); + let avm_bytecode = brillig_to_avm(brillig_bytecode); // Push modified function entry to ABI functions.push(AvmOrAcirContractFunction::Avm(AvmContractFunction { diff --git a/avm-transpiler/src/utils.rs b/avm-transpiler/src/utils.rs index 684dde7b6e4..97667a386c0 100644 --- a/avm-transpiler/src/utils.rs +++ b/avm-transpiler/src/utils.rs @@ -1,33 +1,46 @@ use log::debug; -use acvm::acir::circuit::brillig::Brillig; -use acvm::acir::circuit::Opcode; +use acvm::acir::brillig::Opcode as BrilligOpcode; +use acvm::acir::circuit::{Opcode, Program}; use crate::instructions::AvmInstruction; -/// Extract the Brillig program from its ACIR wrapper instruction. -/// An Noir unconstrained function compiles to one ACIR instruction -/// wrapping a Brillig program. This function just extracts that Brillig -/// assuming the 0th ACIR opcode is the wrapper. -pub fn extract_brillig_from_acir(opcodes: &Vec) -> &Brillig { - if opcodes.len() != 1 { - panic!("An AVM program should be contained entirely in only a single ACIR opcode flagged as 'Brillig'"); - } - let opcode = &opcodes[0]; - match opcode { - Opcode::Brillig(brillig) => brillig, +/// Extract the Brillig program from its `Program` wrapper. +/// Noir entry point unconstrained functions are compiled to their own list contained +/// as part of a full program. Function calls are then accessed through a function +/// pointer opcode in ACIR that fetches those unconstrained functions from the main list. +/// This function just extracts Brillig bytecode, with the assumption that the +/// 0th unconstrained function in the full `Program` structure. +pub fn extract_brillig_from_acir_program(program: &Program) -> &[BrilligOpcode] { + assert_eq!( + program.functions.len(), + 1, + "An AVM program should have only a single ACIR function flagged as 'BrilligCall'" + ); + let opcodes = &program.functions[0].opcodes; + assert_eq!( + opcodes.len(), + 1, + "An AVM program should have only a single ACIR function flagged as 'BrilligCall'" + ); + match opcodes[0] { + Opcode::BrilligCall { .. } => {} _ => panic!("Tried to extract a Brillig program from its ACIR wrapper opcode, but the opcode doesn't contain Brillig!"), } + assert_eq!( + program.unconstrained_functions.len(), + 1, + "An AVM program should be contained entirely in only a single `Brillig` function" + ); + &program.unconstrained_functions[0].bytecode } /// Print inputs, outputs, and instructions in a Brillig program -pub fn dbg_print_brillig_program(brillig: &Brillig) { +pub fn dbg_print_brillig_program(brillig_bytecode: &[BrilligOpcode]) { debug!("Printing Brillig program..."); - debug!("\tInputs: {:?}", brillig.inputs); - for (i, instruction) in brillig.bytecode.iter().enumerate() { + for (i, instruction) in brillig_bytecode.iter().enumerate() { debug!("\tPC:{0} {1:?}", i, instruction); } - debug!("\tOutputs: {:?}", brillig.outputs); } /// Print each instruction in an AVM program diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index afd749485d7..8019707644b 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -360,14 +360,18 @@ impl<'a> Context<'a> { // We specifically do not attempt execution of the brillig code being generated as this can result in it being // replaced with constraints on witnesses to the program outputs. - let output_values = self.acir_context.brillig( + let output_values = self.acir_context.brillig_call( self.current_side_effects_enabled_var, - code, + &code, inputs, outputs, false, true, + // We are guaranteed to have a Brillig function pointer of `0` as main itself is marked as unconstrained + 0, )?; + self.shared_context.insert_generated_brillig(main_func.id(), 0, code); + let output_vars: Vec<_> = output_values .iter() .flat_map(|value| value.clone().flatten()) diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index f3833975def..223a3361fb4 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -68,7 +68,7 @@ export const REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = 0xe7af816635466f128568edb04c9fa024f6c87fb9010fdbffa68b3d99n; export const DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631n; -export const DEPLOYER_CONTRACT_ADDRESS = 0x2b9c3612fc04623512ab47f68537c7b63a90b3efcc39f622f42d1820bfeb93acn; +export const DEPLOYER_CONTRACT_ADDRESS = 0x0b98aeb0111208b95d8d71f484f849d7ab44b3e34c545d13736a707ce3cb0839n; export const L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH = 17; export const MAX_NOTE_FIELDS_LENGTH = 20; export const GET_NOTE_ORACLE_RETURN_LENGTH = 23;