From 8ebbfd8cbe746560d69883422bebab3743ab1bbc Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 11 Apr 2024 20:56:29 +0000 Subject: [PATCH 01/47] initial BrilligPointer opcode without any implementation --- .../dsl/acir_format/serde/acir.hpp | 197 +++++++++++++++++- .../noir-repo/acvm-repo/acir/codegen/acir.cpp | 164 ++++++++++++++- .../acvm-repo/acir/src/circuit/brillig.rs | 18 ++ .../acvm-repo/acir/src/circuit/mod.rs | 7 +- .../acvm-repo/acir/src/circuit/opcodes.rs | 11 +- noir/noir-repo/acvm-repo/acir/src/lib.rs | 8 +- .../acir/tests/test_program_serialization.rs | 17 +- .../acvm/src/compiler/transformers/mod.rs | 14 ++ noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs | 3 + .../backend_interface/src/smart_contract.rs | 2 +- .../tooling/nargo_cli/src/cli/info_cmd.rs | 7 +- 11 files changed, 428 insertions(+), 20 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp index 3e01fd1f1559..490c91d87172 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp @@ -1041,6 +1041,17 @@ struct Brillig { static Brillig bincodeDeserialize(std::vector); }; +struct BrilligPointer { + std::vector inputs; + std::vector outputs; + uint32_t bytecode_index; + std::optional predicate; + + friend bool operator==(const BrilligPointer&, const BrilligPointer&); + std::vector bincodeSerialize() const; + static BrilligPointer bincodeDeserialize(std::vector); +}; + struct Directive { struct ToLeRadix { @@ -1104,6 +1115,14 @@ struct Opcode { static Brillig bincodeDeserialize(std::vector); }; + struct BrilligPointer { + Program::BrilligPointer value; + + friend bool operator==(const BrilligPointer&, const BrilligPointer&); + std::vector bincodeSerialize() const; + static BrilligPointer bincodeDeserialize(std::vector); + }; + struct MemoryOp { Program::BlockId block_id; Program::MemOp op; @@ -1134,7 +1153,7 @@ struct Opcode { static Call bincodeDeserialize(std::vector); }; - std::variant value; + std::variant value; friend bool operator==(const Opcode&, const Opcode&); std::vector bincodeSerialize() const; @@ -1213,8 +1232,17 @@ struct Circuit { static Circuit bincodeDeserialize(std::vector); }; +struct BrilligBytecode { + std::vector bytecode; + + friend bool operator==(const BrilligBytecode&, const BrilligBytecode&); + std::vector bincodeSerialize() const; + static BrilligBytecode bincodeDeserialize(std::vector); +}; + struct Program { std::vector functions; + std::vector unconstrained_functions; friend bool operator==(const Program&, const Program&); std::vector bincodeSerialize() const; @@ -4878,6 +4906,56 @@ Program::Brillig serde::Deserializable::deserialize(Deserializ namespace Program { +inline bool operator==(const BrilligBytecode& lhs, const BrilligBytecode& rhs) +{ + if (!(lhs.bytecode == rhs.bytecode)) { + return false; + } + return true; +} + +inline std::vector BrilligBytecode::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline BrilligBytecode BrilligBytecode::bincodeDeserialize(std::vector input) +{ + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw_or_abort("Some input bytes were not read"); + } + return value; +} + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::BrilligBytecode& obj, + Serializer& serializer) +{ + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.bytecode, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +Program::BrilligBytecode serde::Deserializable::deserialize(Deserializer& deserializer) +{ + deserializer.increase_container_depth(); + Program::BrilligBytecode obj; + obj.bytecode = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace Program { + inline bool operator==(const BrilligInputs& lhs, const BrilligInputs& rhs) { if (!(lhs.value == rhs.value)) { @@ -6224,6 +6302,70 @@ Program::BrilligOutputs::Array serde::Deserializable BrilligPointer::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline BrilligPointer BrilligPointer::bincodeDeserialize(std::vector input) +{ + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw_or_abort("Some input bytes were not read"); + } + return value; +} + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::BrilligPointer& obj, Serializer& serializer) +{ + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.outputs, serializer); + serde::Serializable::serialize(obj.bytecode_index, serializer); + serde::Serializable::serialize(obj.predicate, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +Program::BrilligPointer serde::Deserializable::deserialize(Deserializer& deserializer) +{ + deserializer.increase_container_depth(); + Program::BrilligPointer obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + obj.bytecode_index = serde::Deserializable::deserialize(deserializer); + obj.predicate = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace Program { + inline bool operator==(const Circuit& lhs, const Circuit& rhs) { if (!(lhs.current_witness_index == rhs.current_witness_index)) { @@ -7310,6 +7452,53 @@ Program::Opcode::Brillig serde::Deserializable::deseri namespace Program { +inline bool operator==(const Opcode::BrilligPointer& lhs, const Opcode::BrilligPointer& rhs) +{ + if (!(lhs.value == rhs.value)) { + return false; + } + return true; +} + +inline std::vector Opcode::BrilligPointer::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline Opcode::BrilligPointer Opcode::BrilligPointer::bincodeDeserialize(std::vector input) +{ + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw_or_abort("Some input bytes were not read"); + } + return value; +} + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::Opcode::BrilligPointer& obj, + Serializer& serializer) +{ + serde::Serializable::serialize(obj.value, serializer); +} + +template <> +template +Program::Opcode::BrilligPointer serde::Deserializable::deserialize( + Deserializer& deserializer) +{ + Program::Opcode::BrilligPointer obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Program { + inline bool operator==(const Opcode::MemoryOp& lhs, const Opcode::MemoryOp& rhs) { if (!(lhs.block_id == rhs.block_id)) { @@ -7630,6 +7819,9 @@ inline bool operator==(const Program& lhs, const Program& rhs) if (!(lhs.functions == rhs.functions)) { return false; } + if (!(lhs.unconstrained_functions == rhs.unconstrained_functions)) { + return false; + } return true; } @@ -7658,6 +7850,7 @@ void serde::Serializable::serialize(const Program::Program& ob { serializer.increase_container_depth(); serde::Serializable::serialize(obj.functions, serializer); + serde::Serializable::serialize(obj.unconstrained_functions, serializer); serializer.decrease_container_depth(); } @@ -7668,6 +7861,8 @@ Program::Program serde::Deserializable::deserialize(Deserializ deserializer.increase_container_depth(); Program::Program obj; obj.functions = serde::Deserializable::deserialize(deserializer); + obj.unconstrained_functions = + serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } diff --git a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp index 7cd9fbefba09..ce899df34d07 100644 --- a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp +++ b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp @@ -979,6 +979,17 @@ namespace Program { static Brillig bincodeDeserialize(std::vector); }; + struct BrilligPointer { + std::vector inputs; + std::vector outputs; + uint32_t bytecode_index; + std::optional predicate; + + friend bool operator==(const BrilligPointer&, const BrilligPointer&); + std::vector bincodeSerialize() const; + static BrilligPointer bincodeDeserialize(std::vector); + }; + struct Directive { struct ToLeRadix { @@ -1042,6 +1053,14 @@ namespace Program { static Brillig bincodeDeserialize(std::vector); }; + struct BrilligPointer { + Program::BrilligPointer value; + + friend bool operator==(const BrilligPointer&, const BrilligPointer&); + std::vector bincodeSerialize() const; + static BrilligPointer bincodeDeserialize(std::vector); + }; + struct MemoryOp { Program::BlockId block_id; Program::MemOp op; @@ -1072,7 +1091,7 @@ namespace Program { static Call bincodeDeserialize(std::vector); }; - std::variant value; + std::variant value; friend bool operator==(const Opcode&, const Opcode&); std::vector bincodeSerialize() const; @@ -1151,8 +1170,17 @@ namespace Program { static Circuit bincodeDeserialize(std::vector); }; + struct BrilligBytecode { + std::vector bytecode; + + friend bool operator==(const BrilligBytecode&, const BrilligBytecode&); + std::vector bincodeSerialize() const; + static BrilligBytecode bincodeDeserialize(std::vector); + }; + struct Program { std::vector functions; + std::vector unconstrained_functions; friend bool operator==(const Program&, const Program&); std::vector bincodeSerialize() const; @@ -4071,6 +4099,48 @@ Program::Brillig serde::Deserializable::deserialize(Deserializ return obj; } +namespace Program { + + inline bool operator==(const BrilligBytecode &lhs, const BrilligBytecode &rhs) { + if (!(lhs.bytecode == rhs.bytecode)) { return false; } + return true; + } + + inline std::vector BrilligBytecode::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BrilligBytecode BrilligBytecode::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::BrilligBytecode &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.bytecode, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +Program::BrilligBytecode serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::BrilligBytecode obj; + obj.bytecode = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + namespace Program { inline bool operator==(const BrilligInputs &lhs, const BrilligInputs &rhs) { @@ -5143,6 +5213,57 @@ Program::BrilligOutputs::Array serde::Deserializable BrilligPointer::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BrilligPointer BrilligPointer::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::BrilligPointer &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.outputs, serializer); + serde::Serializable::serialize(obj.bytecode_index, serializer); + serde::Serializable::serialize(obj.predicate, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +Program::BrilligPointer serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::BrilligPointer obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + obj.bytecode_index = serde::Deserializable::deserialize(deserializer); + obj.predicate = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + namespace Program { inline bool operator==(const Circuit &lhs, const Circuit &rhs) { @@ -6033,6 +6154,44 @@ Program::Opcode::Brillig serde::Deserializable::deseri return obj; } +namespace Program { + + inline bool operator==(const Opcode::BrilligPointer &lhs, const Opcode::BrilligPointer &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } + + inline std::vector Opcode::BrilligPointer::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline Opcode::BrilligPointer Opcode::BrilligPointer::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::Opcode::BrilligPointer &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); +} + +template <> +template +Program::Opcode::BrilligPointer serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::BrilligPointer obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; +} + namespace Program { inline bool operator==(const Opcode::MemoryOp &lhs, const Opcode::MemoryOp &rhs) { @@ -6290,6 +6449,7 @@ namespace Program { inline bool operator==(const Program &lhs, const Program &rhs) { if (!(lhs.functions == rhs.functions)) { return false; } + if (!(lhs.unconstrained_functions == rhs.unconstrained_functions)) { return false; } return true; } @@ -6315,6 +6475,7 @@ template void serde::Serializable::serialize(const Program::Program &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.functions, serializer); + serde::Serializable::serialize(obj.unconstrained_functions, serializer); serializer.decrease_container_depth(); } @@ -6324,6 +6485,7 @@ Program::Program serde::Deserializable::deserialize(Deserializ deserializer.increase_container_depth(); Program::Program obj; obj.functions = serde::Deserializable::deserialize(deserializer); + obj.unconstrained_functions = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/brillig.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/brillig.rs index f394a46ff826..146d24ae6ccb 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/brillig.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/brillig.rs @@ -29,3 +29,21 @@ pub struct Brillig { /// Predicate of the Brillig execution - indicates if it should be skipped pub predicate: Option, } + +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct BrilligPointer { + pub inputs: Vec, + pub outputs: Vec, + // A pointer to the index of the Brillig VM bytecode to be executed by the ACVM + pub bytecode_index: u32, + /// Predicate of the Brillig execution - indicates if it should be skipped + pub predicate: Option, +} + +/// This is purely a wrapper struct around a list of Brillig opcode's which represents +/// a full Brillig function to be executed by the Brillig VM. +/// This is stored separately on a program and accessed through a [BrilligPointer]. +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default)] +pub struct BrilligBytecode { + pub bytecode: Vec, +} diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs index cb846bdaffa6..42f21d29bc72 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs @@ -15,6 +15,8 @@ use serde::{de::Error as DeserializationError, Deserialize, Deserializer, Serial use std::collections::BTreeSet; +use self::brillig::BrilligBytecode; + /// Specifies the maximum width of the expressions which will be constrained. /// /// Unbounded Expressions are useful if you are eventually going to pass the ACIR @@ -37,6 +39,7 @@ pub enum ExpressionWidth { #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default)] pub struct Program { pub functions: Vec, + pub unconstrained_functions: Vec, } #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default)] @@ -384,7 +387,7 @@ mod tests { assert_messages: Default::default(), recursive: false, }; - let program = Program { functions: vec![circuit] }; + let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; fn read_write(program: Program) -> (Program, Program) { let bytes = Program::serialize_program(&program); @@ -417,7 +420,7 @@ mod tests { assert_messages: Default::default(), recursive: false, }; - let program = Program { functions: vec![circuit] }; + let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; let json = serde_json::to_string_pretty(&program).unwrap(); diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs index d8204132b3ee..a360aaa61230 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs @@ -1,4 +1,7 @@ -use super::{brillig::Brillig, directives::Directive}; +use super::{ + brillig::{Brillig, BrilligPointer}, + directives::Directive, +}; use crate::native_types::{Expression, Witness}; use serde::{Deserialize, Serialize}; @@ -18,6 +21,7 @@ pub enum Opcode { BlackBoxFuncCall(BlackBoxFuncCall), Directive(Directive), Brillig(Brillig), + BrilligPointer(BrilligPointer), /// Atomic operation on a block of memory MemoryOp { block_id: BlockId, @@ -79,6 +83,11 @@ impl std::fmt::Display for Opcode { writeln!(f, "outputs: {:?}", brillig.outputs)?; writeln!(f, "{:?}", brillig.bytecode) } + Opcode::BrilligPointer(brillig) => { + write!(f, "BRILLIG {:?}: ", brillig.bytecode_index)?; + writeln!(f, "inputs: {:?}", brillig.inputs)?; + writeln!(f, "outputs: {:?}", brillig.outputs) + } Opcode::MemoryOp { block_id, op, predicate } => { write!(f, "MEM ")?; if let Some(pred) = predicate { diff --git a/noir/noir-repo/acvm-repo/acir/src/lib.rs b/noir/noir-repo/acvm-repo/acir/src/lib.rs index d14159f34a16..29e588744781 100644 --- a/noir/noir-repo/acvm-repo/acir/src/lib.rs +++ b/noir/noir-repo/acvm-repo/acir/src/lib.rs @@ -85,10 +85,10 @@ mod reflection { generator.output(&mut source, ®istry).unwrap(); // Comment this out to write updated C++ code to file. - if let Some(old_hash) = old_hash { - let new_hash = fxhash::hash64(&source); - assert_eq!(new_hash, old_hash, "Serialization format has changed"); - } + // if let Some(old_hash) = old_hash { + // let new_hash = fxhash::hash64(&source); + // assert_eq!(new_hash, old_hash, "Serialization format has changed"); + // } write_to_file(&source, &path); } diff --git a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs index 8b9160ccf6a4..c067ee87b7b4 100644 --- a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs +++ b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs @@ -41,7 +41,7 @@ fn addition_circuit() { return_values: PublicInputs([Witness(3)].into()), ..Circuit::default() }; - let program = Program { functions: vec![circuit] }; + let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; let bytes = Program::serialize_program(&program); @@ -72,7 +72,7 @@ fn fixed_base_scalar_mul_circuit() { return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(3), Witness(4)])), ..Circuit::default() }; - let program = Program { functions: vec![circuit] }; + let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; let bytes = Program::serialize_program(&program); @@ -100,7 +100,7 @@ fn pedersen_circuit() { return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(2), Witness(3)])), ..Circuit::default() }; - let program = Program { functions: vec![circuit] }; + let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; let bytes = Program::serialize_program(&program); @@ -142,7 +142,7 @@ fn schnorr_verify_circuit() { return_values: PublicInputs(BTreeSet::from([output])), ..Circuit::default() }; - let program = Program { functions: vec![circuit] }; + let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; let bytes = Program::serialize_program(&program); @@ -206,7 +206,7 @@ fn simple_brillig_foreign_call() { private_parameters: BTreeSet::from([Witness(1), Witness(2)]), ..Circuit::default() }; - let program = Program { functions: vec![circuit] }; + let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; let bytes = Program::serialize_program(&program); @@ -306,7 +306,7 @@ fn complex_brillig_foreign_call() { private_parameters: BTreeSet::from([Witness(1), Witness(2), Witness(3)]), ..Circuit::default() }; - let program = Program { functions: vec![circuit] }; + let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; let bytes = Program::serialize_program(&program); @@ -348,7 +348,7 @@ fn memory_op_circuit() { return_values: PublicInputs([Witness(4)].into()), ..Circuit::default() }; - let program = Program { functions: vec![circuit] }; + let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; let bytes = Program::serialize_program(&program); @@ -450,7 +450,8 @@ fn nested_acir_call_circuit() { ..Circuit::default() }; - let program = Program { functions: vec![main, nested_call, inner_call] }; + let program = + Program { functions: vec![main, nested_call, inner_call], unconstrained_functions: vec![] }; let bytes = Program::serialize_program(&program); diff --git a/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs index 003cd4279a11..12f7a8b0174c 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -142,6 +142,20 @@ pub(super) fn transform_internal( new_acir_opcode_positions.push(acir_opcode_positions[index]); transformed_opcodes.push(opcode); } + Opcode::BrilligPointer(ref brillig) => { + for output in &brillig.outputs { + match output { + BrilligOutputs::Simple(w) => transformer.mark_solvable(*w), + BrilligOutputs::Array(v) => { + for witness in v { + transformer.mark_solvable(*witness); + } + } + } + } + new_acir_opcode_positions.push(acir_opcode_positions[index]); + transformed_opcodes.push(opcode); + } Opcode::Call { ref outputs, .. } => { for witness in outputs { transformer.mark_solvable(*witness); diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index bb98eda2689b..b99453ace6a6 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -324,6 +324,9 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { Ok(Some(foreign_call)) => return self.wait_for_foreign_call(foreign_call), res => res.map(|_| ()), }, + Opcode::BrilligPointer(_) => { + todo!("implement brillig pointer handling"); + } Opcode::Call { .. } => match self.solve_call_opcode() { Ok(Some(input_values)) => return self.wait_for_acir_call(input_values), res => res.map(|_| ()), diff --git a/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs b/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs index f6beeeb09d99..cd665c60fb14 100644 --- a/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs +++ b/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs @@ -59,7 +59,7 @@ mod tests { assert_messages: Default::default(), recursive: false, }; - let program = Program { functions: vec![circuit] }; + let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; let contract = get_mock_backend()?.eth_contract(&program)?; diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs index 72784013e173..7c936f98fd59 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs @@ -289,8 +289,11 @@ fn count_opcodes_and_gates_in_program( Ok(FunctionInfo { name: compiled_program.names[i].clone(), acir_opcodes: function.opcodes.len(), - circuit_size: backend - .get_exact_circuit_size(&Program { functions: vec![function] })?, + // TODO: update serialization on backend. Unconstrained funcs will not matter here though + circuit_size: backend.get_exact_circuit_size(&Program { + functions: vec![function], + unconstrained_functions: vec![], + })?, }) }) .collect::>()?; From be85a535db8a308b34a4e71366cb0e13f99218db Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 12 Apr 2024 13:23:21 +0000 Subject: [PATCH 02/47] initial codegen work for brillig pointer and execution in the acvm --- .../acvm-repo/acir/src/circuit/mod.rs | 4 + .../acvm-repo/acvm/src/pwg/brillig.rs | 77 +++++++++++-- noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs | 79 ++++++++++++-- .../compiler/noirc_evaluator/src/ssa.rs | 23 +++- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 93 ++++++++++++++++ .../ssa/acir_gen/acir_ir/generated_acir.rs | 31 +++++- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 102 ++++++++++++++---- .../src/ssa/ssa_gen/program.rs | 19 +++- .../brillig_acir_loop/Nargo.toml | 7 ++ .../brillig_acir_loop/Prover.toml | 2 + .../brillig_acir_loop/src/main.nr | 15 +++ .../noir-repo/tooling/debugger/src/context.rs | 12 ++- noir/noir-repo/tooling/debugger/src/dap.rs | 4 + noir/noir-repo/tooling/debugger/src/lib.rs | 4 +- noir/noir-repo/tooling/debugger/src/repl.rs | 10 +- .../tooling/nargo/src/ops/execute.rs | 10 +- .../tooling/nargo_cli/src/cli/debug_cmd.rs | 1 + 17 files changed, 443 insertions(+), 50 deletions(-) create mode 100644 noir/noir-repo/test_programs/execution_success/brillig_acir_loop/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/brillig_acir_loop/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/brillig_acir_loop/src/main.nr diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs index 42f21d29bc72..53e6b10a5bce 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs @@ -266,6 +266,10 @@ impl std::fmt::Display for Program { writeln!(f, "func {}", func_index)?; writeln!(f, "{}", function)?; } + for (func_index, function) in self.unconstrained_functions.iter().enumerate() { + writeln!(f, "unconstrained func {}", func_index)?; + writeln!(f, "{:?}", function.bytecode)?; + } Ok(()) } } diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs index 81e752d5656e..9d16fddb857a 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs @@ -1,9 +1,9 @@ use std::collections::HashMap; use acir::{ - brillig::{ForeignCallParam, ForeignCallResult}, + brillig::{ForeignCallParam, ForeignCallResult, Opcode as BrilligOpcode}, circuit::{ - brillig::{Brillig, BrilligInputs, BrilligOutputs}, + brillig::{Brillig, BrilligInputs, BrilligOutputs, BrilligPointer}, opcodes::BlockId, OpcodeLocation, }, @@ -46,9 +46,9 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { /// Assigns the zero value to all outputs of the given [`Brillig`] bytecode. pub(super) fn zero_out_brillig_outputs( initial_witness: &mut WitnessMap, - brillig: &Brillig, + outputs: &[BrilligOutputs], ) -> Result<(), OpcodeResolutionError> { - for output in &brillig.outputs { + for output in outputs { match output { BrilligOutputs::Simple(witness) => { insert_value(witness, FieldElement::zero(), initial_witness)?; @@ -63,6 +63,7 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { Ok(()) } + // TODO: delete this old method /// Constructs a solver for a Brillig block given the bytecode and initial /// witness. pub(crate) fn new( @@ -122,6 +123,66 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { Ok(Self { vm, acir_index }) } + /// Constructs a solver for a Brillig block given the bytecode and initial + /// witness. + pub(crate) fn new_with_pointer( + initial_witness: &WitnessMap, + memory: &HashMap, + brillig_pointer: &'b BrilligPointer, + brillig_bytecode: &'b [BrilligOpcode], + bb_solver: &'b B, + acir_index: usize, + ) -> Result { + // Set input values + let mut calldata: Vec = Vec::new(); + // Each input represents an expression or array of expressions to evaluate. + // Iterate over each input and evaluate the expression(s) associated with it. + // Push the results into memory. + // If a certain expression is not solvable, we stall the ACVM and do not proceed with Brillig VM execution. + for input in &brillig_pointer.inputs { + match input { + BrilligInputs::Single(expr) => match get_value(expr, initial_witness) { + Ok(value) => calldata.push(value), + Err(_) => { + return Err(OpcodeResolutionError::OpcodeNotSolvable( + OpcodeNotSolvable::ExpressionHasTooManyUnknowns(expr.clone()), + )) + } + }, + BrilligInputs::Array(expr_arr) => { + // Attempt to fetch all array input values + for expr in expr_arr.iter() { + match get_value(expr, initial_witness) { + Ok(value) => calldata.push(value), + Err(_) => { + return Err(OpcodeResolutionError::OpcodeNotSolvable( + OpcodeNotSolvable::ExpressionHasTooManyUnknowns(expr.clone()), + )) + } + } + } + } + BrilligInputs::MemoryArray(block_id) => { + let memory_block = memory + .get(block_id) + .ok_or(OpcodeNotSolvable::MissingMemoryBlock(block_id.0))?; + for memory_index in 0..memory_block.block_len { + let memory_value = memory_block + .block_value + .get(&memory_index) + .expect("All memory is initialized on creation"); + calldata.push(*memory_value); + } + } + } + } + + // Instantiate a Brillig VM given the solved calldata + // along with the Brillig bytecode. + let vm = VM::new(calldata, brillig_bytecode, vec![], bb_solver); + Ok(Self { vm, acir_index }) + } + pub fn get_memory(&self) -> &[MemoryValue] { self.vm.get_memory() } @@ -180,13 +241,13 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { pub(crate) fn finalize( self, witness: &mut WitnessMap, - brillig: &Brillig, + outputs: &[BrilligOutputs], ) -> Result<(), OpcodeResolutionError> { // Finish the Brillig execution by writing the outputs to the witness map let vm_status = self.vm.get_status(); match vm_status { VMStatus::Finished { return_data_offset, return_data_size } => { - self.write_brillig_outputs(witness, return_data_offset, return_data_size, brillig)?; + self.write_brillig_outputs(witness, return_data_offset, return_data_size, outputs)?; Ok(()) } _ => panic!("Brillig VM has not completed execution"), @@ -198,12 +259,12 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { witness_map: &mut WitnessMap, return_data_offset: usize, return_data_size: usize, - brillig: &Brillig, + outputs: &[BrilligOutputs], ) -> Result<(), OpcodeResolutionError> { // Write VM execution results into the witness map let memory = self.vm.get_memory(); let mut current_ret_data_idx = return_data_offset; - for output in brillig.outputs.iter() { + for output in outputs.iter() { match output { BrilligOutputs::Simple(witness) => { insert_value(witness, memory[current_ret_data_idx].to_field(), witness_map)?; diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index b99453ace6a6..82a8b3d5fabd 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use acir::{ brillig::ForeignCallResult, - circuit::{opcodes::BlockId, Opcode, OpcodeLocation}, + circuit::{brillig::{Brillig, BrilligBytecode}, opcodes::BlockId, Opcode, OpcodeLocation}, native_types::{Expression, Witness, WitnessMap}, BlackBoxFunc, FieldElement, }; @@ -165,10 +165,17 @@ pub struct ACVM<'a, B: BlackBoxFunctionSolver> { /// Represents the outputs of all ACIR calls during an ACVM process /// List is appended onto by the caller upon reaching a [ACVMStatus::RequiresAcirCall] acir_call_results: Vec>, + + // A counter maintained through an ACVM process that determines + // whether the caller has resolved the bytecode of a Brillig pointer + // brillig_call_counter: usize, + // Represents the bytecode pointer + // brillig_bytecodes: Vec< + unconstrained_functions: &'a [BrilligBytecode], } impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { - pub fn new(backend: &'a B, opcodes: &'a [Opcode], initial_witness: WitnessMap) -> Self { + pub fn new(backend: &'a B, opcodes: &'a [Opcode], initial_witness: WitnessMap, unconstrained_functions: &'a [BrilligBytecode]) -> Self { let status = if opcodes.is_empty() { ACVMStatus::Solved } else { ACVMStatus::InProgress }; ACVM { status, @@ -181,6 +188,7 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { brillig_solver: None, acir_call_counter: 0, acir_call_results: Vec::default(), + unconstrained_functions } } @@ -324,9 +332,10 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { Ok(Some(foreign_call)) => return self.wait_for_foreign_call(foreign_call), res => res.map(|_| ()), }, - Opcode::BrilligPointer(_) => { - todo!("implement brillig pointer handling"); - } + Opcode::BrilligPointer(_) => match self.solve_brillig_pointer_opcode() { + Ok(Some(foreign_call)) => return self.wait_for_foreign_call(foreign_call), + res => res.map(|_| ()), + }, Opcode::Call { .. } => match self.solve_call_opcode() { Ok(Some(input_values)) => return self.wait_for_acir_call(input_values), res => res.map(|_| ()), @@ -381,7 +390,7 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { let witness = &mut self.witness_map; if is_predicate_false(witness, &brillig.predicate)? { - return BrilligSolver::::zero_out_brillig_outputs(witness, brillig).map(|_| None); + return BrilligSolver::::zero_out_brillig_outputs(witness, &brillig.outputs).map(|_| None); } // If we're resuming execution after resolving a foreign call then @@ -407,7 +416,51 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { } BrilligSolverStatus::Finished => { // Write execution outputs - solver.finalize(witness, brillig)?; + solver.finalize(witness, &brillig.outputs)?; + Ok(None) + } + } + } + + fn solve_brillig_pointer_opcode( + &mut self, + ) -> Result, OpcodeResolutionError> { + let Opcode::BrilligPointer(brillig_pointer) = &self.opcodes[self.instruction_pointer] else { + unreachable!("Not executing a Brillig opcode"); + }; + + let witness = &mut self.witness_map; + if is_predicate_false(witness, &brillig_pointer.predicate)? { + return BrilligSolver::::zero_out_brillig_outputs(witness, &brillig_pointer.outputs).map(|_| None); + } + + // If we're resuming execution after resolving a foreign call then + // there will be a cached `BrilligSolver` to avoid recomputation. + let mut solver: BrilligSolver<'_, B> = match self.brillig_solver.take() { + Some(solver) => solver, + None => { + BrilligSolver::new_with_pointer( + witness, + &self.block_solvers, + brillig_pointer, + &self.unconstrained_functions[brillig_pointer.bytecode_index as usize].bytecode, + self.backend, + self.instruction_pointer, + )? + } + }; + match solver.solve()? { + BrilligSolverStatus::ForeignCallWait(foreign_call) => { + // Cache the current state of the solver + self.brillig_solver = Some(solver); + Ok(Some(foreign_call)) + } + BrilligSolverStatus::InProgress => { + unreachable!("Brillig solver still in progress") + } + BrilligSolverStatus::Finished => { + // Write execution outputs + solver.finalize(witness, &brillig_pointer.outputs)?; Ok(None) } } @@ -425,7 +478,7 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { }; if should_skip { - let resolution = BrilligSolver::::zero_out_brillig_outputs(witness, brillig); + let resolution = BrilligSolver::::zero_out_brillig_outputs(witness, &brillig.outputs); return StepResult::Status(self.handle_opcode_resolution(resolution)); } @@ -499,6 +552,16 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { self.acir_call_counter += 1; Ok(None) } + + // fn solve_brillig_pointer_opcode(&mut self) -> Result, OpcodeResolutionError> { + // if is_predicate_false(&self.witness_map, predicate)? { + // // Zero out the outputs if we have a false predicate + // for output in outputs { + // insert_value(output, FieldElement::zero(), &mut self.witness_map)?; + // } + // return Ok(None); + // } + // } } // Returns the concrete value for a particular witness diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index fac7a7c08296..a72e962b59a3 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -14,7 +14,7 @@ use crate::{ errors::{RuntimeError, SsaReport}, }; use acvm::acir::{ - circuit::{Circuit, ExpressionWidth, Program as AcirProgram, PublicInputs}, + circuit::{brillig::BrilligBytecode, Circuit, ExpressionWidth, Program as AcirProgram, PublicInputs}, native_types::Witness, }; @@ -42,7 +42,7 @@ pub(crate) fn optimize_into_acir( print_brillig_trace: bool, force_brillig_output: bool, print_timings: bool, -) -> Result, RuntimeError> { +) -> Result<(Vec, Vec), RuntimeError> { let abi_distinctness = program.return_distinctness; let ssa_gen_span = span!(Level::TRACE, "ssa_generation"); @@ -99,6 +99,21 @@ pub struct SsaProgramArtifact { } impl SsaProgramArtifact { + fn new(unconstrained_functions: Vec) -> Self { + let program = AcirProgram { + functions: Vec::default(), + unconstrained_functions, + }; + Self { + program, + debug: Vec::default(), + warnings: Vec::default(), + main_input_witnesses: Vec::default(), + main_return_witnesses: Vec::default(), + names: Vec::default(), + } + } + fn add_circuit(&mut self, mut circuit_artifact: SsaCircuitArtifact, is_main: bool) { self.program.functions.push(circuit_artifact.circuit); self.debug.push(circuit_artifact.debug_info); @@ -130,7 +145,7 @@ pub fn create_program( let func_sigs = program.function_signatures.clone(); let recursive = program.recursive; - let generated_acirs = optimize_into_acir( + let (generated_acirs, brillig_bytecode) = optimize_into_acir( program, enable_ssa_logging, enable_brillig_logging, @@ -143,7 +158,7 @@ pub fn create_program( "The generated ACIRs should match the supplied function signatures" ); - let mut program_artifact = SsaProgramArtifact::default(); + let mut program_artifact = SsaProgramArtifact::new(brillig_bytecode); // For setting up the ABI we need separately specify main's input and return witnesses let mut is_main = true; for (acir, func_sig) in generated_acirs.into_iter().zip(func_sigs) { diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 775571f4a413..79613e1e5d51 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1553,6 +1553,99 @@ impl AcirContext { Ok(outputs_var) } + pub(crate) fn brillig_pointer( + &mut self, + predicate: AcirVar, + generated_brillig: &GeneratedBrillig, + inputs: Vec, + outputs: Vec, + attempt_execution: bool, + unsafe_return_values: bool, + brillig_function_index: u32, + ) -> Result, RuntimeError> { + // TODO: move this to its own method + let b_inputs = try_vecmap(inputs, |i| -> Result<_, InternalError> { + match i { + AcirValue::Var(var, _) => Ok(BrilligInputs::Single(self.var_to_expression(var)?)), + AcirValue::Array(vars) => { + let mut var_expressions: Vec = Vec::new(); + for var in vars { + self.brillig_array_input(&mut var_expressions, var)?; + } + Ok(BrilligInputs::Array(var_expressions)) + } + AcirValue::DynamicArray(AcirDynamicArray { block_id, .. }) => { + Ok(BrilligInputs::MemoryArray(block_id)) + } + } + })?; + + // Optimistically try executing the brillig now, if we can complete execution they just return the results. + // This is a temporary measure pending SSA optimizations being applied to Brillig which would remove constant-input opcodes (See #2066) + // + // We do _not_ want to do this in the situation where the `main` function is unconstrained, as if execution succeeds + // the entire program will be replaced with witness constraints to its outputs. + if attempt_execution { + if let Some(brillig_outputs) = + self.execute_brillig(&generated_brillig.byte_code, &b_inputs, &outputs) + { + return Ok(brillig_outputs); + } + } + + // Otherwise we must generate ACIR for it and execute at runtime. + let mut b_outputs = Vec::new(); + let outputs_var = vecmap(outputs, |output| match output { + AcirType::NumericType(_) => { + let witness_index = self.acir_ir.next_witness_index(); + b_outputs.push(BrilligOutputs::Simple(witness_index)); + let var = self.add_data(AcirVarData::Witness(witness_index)); + AcirValue::Var(var, output.clone()) + } + AcirType::Array(element_types, size) => { + let (acir_value, witnesses) = self.brillig_array_output(&element_types, size); + b_outputs.push(BrilligOutputs::Array(witnesses)); + acir_value + } + }); + let predicate = self.var_to_expression(predicate)?; + + self.acir_ir.brillig_pointer(Some(predicate), &generated_brillig, b_inputs, b_outputs, brillig_function_index); + + fn range_constraint_value( + context: &mut AcirContext, + value: &AcirValue, + ) -> Result<(), RuntimeError> { + match value { + AcirValue::Var(var, typ) => { + let numeric_type = match typ { + AcirType::NumericType(numeric_type) => numeric_type, + _ => unreachable!("`AcirValue::Var` may only hold primitive values"), + }; + context.range_constrain_var(*var, numeric_type, None)?; + } + AcirValue::Array(values) => { + for value in values { + range_constraint_value(context, value)?; + } + } + AcirValue::DynamicArray(_) => { + unreachable!("Brillig opcodes cannot return dynamic arrays") + } + } + Ok(()) + } + + // This is a hack to ensure that if we're compiling a brillig entrypoint function then + // we don't also add a number of range constraints. + if !unsafe_return_values { + for output_var in &outputs_var { + range_constraint_value(self, output_var)?; + } + } + Ok(outputs_var) + } + fn brillig_array_input( &mut self, var_expressions: &mut Vec, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index ba4e03bff955..725dde575ac9 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -10,7 +10,7 @@ use crate::{ use acvm::acir::{ circuit::{ - brillig::{Brillig as AcvmBrillig, BrilligInputs, BrilligOutputs}, + brillig::{Brillig as AcvmBrillig, BrilligInputs, BrilligOutputs, BrilligPointer}, opcodes::{BlackBoxFuncCall, FunctionInput, Opcode as AcirOpcode}, OpcodeLocation, }, @@ -567,6 +567,35 @@ impl GeneratedAcir { } } + pub(crate) fn brillig_pointer( + &mut self, + predicate: Option, + generated_brillig: &GeneratedBrillig, + inputs: Vec, + outputs: Vec, + brillig_function_index: u32, + ) { + let opcode = AcirOpcode::BrilligPointer(BrilligPointer { + inputs, + outputs, + bytecode_index: brillig_function_index, + predicate, + }); + self.push_opcode(opcode); + for (brillig_index, call_stack) in generated_brillig.locations.iter() { + self.locations.insert( + OpcodeLocation::Brillig { acir_index: self.opcodes.len() - 1, brillig_index: *brillig_index }, + call_stack.clone(), + ); + } + for (brillig_index, message) in generated_brillig.assert_messages.iter() { + self.assert_messages.insert( + OpcodeLocation::Brillig { acir_index: self.opcodes.len() - 1, brillig_index: *brillig_index }, + message.clone(), + ); + } + } + pub(crate) fn last_acir_opcode_location(&self) -> OpcodeLocation { OpcodeLocation::Acir(self.opcodes.len() - 1) } 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 9f2cec5c9490..787d54f96330 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 @@ -28,6 +28,7 @@ use crate::errors::{InternalError, InternalWarning, RuntimeError, SsaReport}; use crate::ssa::ir::function::InlineType; pub(crate) use acir_ir::generated_acir::GeneratedAcir; +use acvm::acir::circuit::brillig::BrilligBytecode; use acvm::acir::native_types::Witness; use acvm::acir::BlackBoxFunc; use acvm::{ @@ -41,7 +42,7 @@ use noirc_frontend::Distinctness; /// Context struct for the acir generation pass. /// May be similar to the Evaluator struct in the current SSA IR. -struct Context { +struct Context<'a> { /// Maps SSA values to `AcirVar`. /// /// This is needed so that we only create a single @@ -91,6 +92,9 @@ struct Context { max_block_id: u32, data_bus: DataBus, + + // TODO: could make this a Vec as the IDs have already made to be consecutive indices + generated_brillig_map: &'a mut HashMap } #[derive(Clone)] @@ -181,11 +185,13 @@ impl Ssa { self, brillig: &Brillig, abi_distinctness: Distinctness, - ) -> Result, RuntimeError> { + ) -> Result<(Vec, Vec), RuntimeError> { let mut acirs = Vec::new(); // TODO: can we parallelise this? + let mut generated_brillig_map = HashMap::default(); for function in self.functions.values() { - let context = Context::new(); + // let context = Context::new(); + let context = Context::new_with_brillig_map(&mut generated_brillig_map); if let Some(mut generated_acir) = context.convert_ssa_function(&self, function, brillig)? { @@ -193,6 +199,9 @@ impl Ssa { acirs.push(generated_acir); } } + + // TODO: can just store the Brillig bytecode as we utilize the locations when setting acir locations + let brilligs = generated_brillig_map.iter().map(|(_, brillig)| BrilligBytecode { bytecode: brillig.byte_code.clone() }).collect::>(); // TODO: check whether doing this for a single circuit's return witnesses is correct. // We probably need it for all foldable circuits, as any circuit being folded is essentially an entry point. However, I do not know how that @@ -215,15 +224,34 @@ impl Ssa { .collect(); main_func_acir.return_witnesses = distinct_return_witness; - Ok(acirs) + // Ok(acirs) } - Distinctness::DuplicationAllowed => Ok(acirs), + Distinctness::DuplicationAllowed => {} + // Distinctness::DuplicationAllowed => Ok(acirs), } + Ok((acirs, brilligs)) } } -impl Context { - fn new() -> Context { +impl<'a> Context<'a> { + // fn new() -> Self { + // let mut acir_context = AcirContext::default(); + // let current_side_effects_enabled_var = acir_context.add_constant(FieldElement::one()); + // Context { + // ssa_values: HashMap::default(), + // current_side_effects_enabled_var, + // acir_context, + // initialized_arrays: HashSet::new(), + // memory_blocks: HashMap::default(), + // internal_memory_blocks: HashMap::default(), + // internal_mem_block_lengths: HashMap::default(), + // max_block_id: 0, + // data_bus: DataBus::default(), + // generated_brillig_map: HashMap::default(), + // } + // } + + fn new_with_brillig_map(generated_brillig_map: &mut HashMap) -> Context { let mut acir_context = AcirContext::default(); let current_side_effects_enabled_var = acir_context.add_constant(FieldElement::one()); @@ -237,6 +265,7 @@ impl Context { internal_mem_block_lengths: HashMap::default(), max_block_id: 0, data_bus: DataBus::default(), + generated_brillig_map, } } @@ -598,24 +627,55 @@ impl Context { ); } } + let brillig_program_id = ssa + .id_to_index + .get(id) + .expect("ICE: should have an associated final index"); + dbg!(brillig_program_id); let inputs = vecmap(arguments, |arg| self.convert_value(*arg, dfg)); - let arguments = self.gen_brillig_parameters(arguments, dfg); - - let code = self.gen_brillig_for(func, arguments, brillig)?; let outputs: Vec = vecmap(result_ids, |result_id| { dfg.type_of_value(*result_id).into() }); - let output_values = self.acir_context.brillig( - self.current_side_effects_enabled_var, - code, - inputs, - outputs, - true, - false, - )?; + let output_values = if let Some(code) = self.generated_brillig_map.get(brillig_program_id) { + dbg!("got previous generated brillig"); + self.acir_context.brillig_pointer( + self.current_side_effects_enabled_var, + code, + inputs, + outputs, + true, + false, + *brillig_program_id, + )? + } else { + let arguments = self.gen_brillig_parameters(arguments, dfg); + let code = self.gen_brillig_for(func, arguments, brillig)?; + // dbg!(code.byte_code.clone()); + let output_values = self.acir_context.brillig_pointer( + self.current_side_effects_enabled_var, + &code, + inputs, + outputs, + true, + false, + *brillig_program_id, + )?; + + self.generated_brillig_map.insert(*brillig_program_id, code); + output_values + }; + + // let output_values = self.acir_context.brillig( + // self.current_side_effects_enabled_var, + // code, + // inputs, + // outputs, + // true, + // false, + // )?; // Compiler sanity check assert_eq!(result_ids.len(), output_values.len(), "ICE: The number of Brillig output values should match the result ids in SSA"); @@ -2492,7 +2552,7 @@ mod test { let ssa = builder.finish(); - let acir_functions = ssa + let (acir_functions, _) = ssa .into_acir(&Brillig::default(), noirc_frontend::Distinctness::Distinct) .expect("Should compile manually written SSA into ACIR"); // Expected result: @@ -2588,7 +2648,7 @@ mod test { let ssa = builder.finish(); - let acir_functions = ssa + let (acir_functions, _) = ssa .into_acir(&Brillig::default(), noirc_frontend::Distinctness::Distinct) .expect("Should compile manually written SSA into ACIR"); // The expected result should look very similar to the abvoe test expect that the input witnesses of the `Call` @@ -2679,7 +2739,7 @@ mod test { let ssa = builder.finish(); - let acir_functions = ssa + let (acir_functions, _) = ssa .into_acir(&Brillig::default(), noirc_frontend::Distinctness::Distinct) .expect("Should compile manually written SSA into ACIR"); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs index 9995c031145e..0c8093ceee7f 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs @@ -3,7 +3,7 @@ use std::{collections::BTreeMap, fmt::Display}; use iter_extended::btree_map; use crate::ssa::ir::{ - function::{Function, FunctionId}, + function::{Function, FunctionId, RuntimeType}, map::AtomicCounter, }; @@ -27,7 +27,22 @@ impl Ssa { (f.id(), f) }); - let id_to_index = btree_map(functions.iter().enumerate(), |(i, (id, _))| (*id, i as u32)); + let mut acir_index = 0; + let mut brillig_index = 0; + let id_to_index = btree_map(functions.iter().enumerate(), |(i, (id, func))| { + match func.runtime() { + RuntimeType::Acir(_) => { + let res = (*id, acir_index); + acir_index += 1; + res + } + RuntimeType::Brillig => { + let res = (*id, brillig_index); + brillig_index += 1; + res + } + } + }); Self { functions, main_id, next_id: AtomicCounter::starting_after(max_id), id_to_index } } diff --git a/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/Nargo.toml b/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/Nargo.toml new file mode 100644 index 000000000000..3ae4448bbcf7 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "brillig_acir_loop" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/Prover.toml b/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/Prover.toml new file mode 100644 index 000000000000..f28f2f8cc48f --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" diff --git a/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/src/main.nr new file mode 100644 index 000000000000..a5883e796069 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/src/main.nr @@ -0,0 +1,15 @@ +fn main(x: Field, y: pub Field) { + // foo(x, y); + for _ in 0..4 { + foo(x, y); + // check_values(x, y); + } +} + +unconstrained fn foo(x: Field, y: Field) { + check_values(x, y); +} + +unconstrained fn check_values(x: Field, y: Field) { + assert(x != y); +} diff --git a/noir/noir-repo/tooling/debugger/src/context.rs b/noir/noir-repo/tooling/debugger/src/context.rs index b211832518d4..8f7cf8dc9013 100644 --- a/noir/noir-repo/tooling/debugger/src/context.rs +++ b/noir/noir-repo/tooling/debugger/src/context.rs @@ -1,4 +1,5 @@ use crate::foreign_calls::DebugForeignCallExecutor; +use acvm::acir::circuit::brillig::BrilligBytecode; use acvm::acir::circuit::{Circuit, Opcode, OpcodeLocation}; use acvm::acir::native_types::{Witness, WitnessMap}; use acvm::brillig_vm::brillig::ForeignCallResult; @@ -42,10 +43,12 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { debug_artifact: &'a DebugArtifact, initial_witness: WitnessMap, foreign_call_executor: Box, + unconstrained_functions: &'a [BrilligBytecode], ) -> Self { let source_to_opcodes = build_source_to_opcode_debug_mappings(debug_artifact); Self { - acvm: ACVM::new(blackbox_solver, &circuit.opcodes, initial_witness), + // TODO: need to handle brillig in the debugger + acvm: ACVM::new(blackbox_solver, &circuit.opcodes, initial_witness, unconstrained_functions), brillig_solver: None, foreign_call_executor, debug_artifact, @@ -630,6 +633,7 @@ fn build_source_to_opcode_debug_mappings( result } +// TODO: update all debugger tests to use unconstrained brillig pointers #[cfg(test)] mod tests { use super::*; @@ -696,12 +700,14 @@ mod tests { let foreign_call_executor = Box::new(DefaultDebugForeignCallExecutor::from_artifact(true, debug_artifact)); + let brillig_funcs = &vec![]; let mut context = DebugContext::new( &StubbedBlackBoxSolver, circuit, debug_artifact, initial_witness, foreign_call_executor, + brillig_funcs, ); assert_eq!(context.get_current_opcode_location(), Some(OpcodeLocation::Acir(0))); @@ -803,12 +809,14 @@ mod tests { let foreign_call_executor = Box::new(DefaultDebugForeignCallExecutor::from_artifact(true, debug_artifact)); + let brillig_funcs = &vec![]; let mut context = DebugContext::new( &StubbedBlackBoxSolver, circuit, debug_artifact, initial_witness, foreign_call_executor, + brillig_funcs, ); // set breakpoint @@ -860,12 +868,14 @@ mod tests { let circuit = Circuit { opcodes, ..Circuit::default() }; let debug_artifact = DebugArtifact { debug_symbols: vec![], file_map: BTreeMap::new(), warnings: vec![] }; + let brillig_funcs = &vec![]; let context = DebugContext::new( &StubbedBlackBoxSolver, &circuit, &debug_artifact, WitnessMap::new(), Box::new(DefaultDebugForeignCallExecutor::new(true)), + brillig_funcs, ); assert_eq!(context.offset_opcode_location(&None, 0), (None, 0)); diff --git a/noir/noir-repo/tooling/debugger/src/dap.rs b/noir/noir-repo/tooling/debugger/src/dap.rs index ea3204ebbbc1..3f32cd8d809f 100644 --- a/noir/noir-repo/tooling/debugger/src/dap.rs +++ b/noir/noir-repo/tooling/debugger/src/dap.rs @@ -2,6 +2,7 @@ use std::collections::BTreeMap; use std::io::{Read, Write}; use std::str::FromStr; +use acvm::acir::circuit::brillig::BrilligBytecode; use acvm::acir::circuit::{Circuit, OpcodeLocation}; use acvm::acir::native_types::WitnessMap; use acvm::BlackBoxFunctionSolver; @@ -64,6 +65,7 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { circuit: &'a Circuit, debug_artifact: &'a DebugArtifact, initial_witness: WitnessMap, + unconstrained_functions: &'a [BrilligBytecode], ) -> Self { let context = DebugContext::new( solver, @@ -71,6 +73,7 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { debug_artifact, initial_witness, Box::new(DefaultDebugForeignCallExecutor::from_artifact(true, debug_artifact)), + unconstrained_functions ); Self { server, @@ -613,6 +616,7 @@ pub fn run_session( &program.program.functions[0], &debug_artifact, initial_witness, + &program.program.unconstrained_functions, ); session.run_loop() diff --git a/noir/noir-repo/tooling/debugger/src/lib.rs b/noir/noir-repo/tooling/debugger/src/lib.rs index 4a25e3417a07..c4bbd51b8b68 100644 --- a/noir/noir-repo/tooling/debugger/src/lib.rs +++ b/noir/noir-repo/tooling/debugger/src/lib.rs @@ -7,6 +7,7 @@ mod source_code_printer; use std::io::{Read, Write}; +use acvm::acir::circuit::brillig::BrilligBytecode; use ::dap::errors::ServerError; use ::dap::server::Server; use acvm::BlackBoxFunctionSolver; @@ -22,8 +23,9 @@ pub fn debug_circuit( circuit: &Circuit, debug_artifact: DebugArtifact, initial_witness: WitnessMap, + unconstrained_functions: &[BrilligBytecode], ) -> Result, NargoError> { - repl::run(blackbox_solver, circuit, &debug_artifact, initial_witness) + repl::run(blackbox_solver, circuit, &debug_artifact, initial_witness, unconstrained_functions) } pub fn run_dap_loop( diff --git a/noir/noir-repo/tooling/debugger/src/repl.rs b/noir/noir-repo/tooling/debugger/src/repl.rs index e30d519b62e8..9f175862bbb2 100644 --- a/noir/noir-repo/tooling/debugger/src/repl.rs +++ b/noir/noir-repo/tooling/debugger/src/repl.rs @@ -1,5 +1,6 @@ use crate::context::{DebugCommandResult, DebugContext}; +use acvm::acir::circuit::brillig::BrilligBytecode; use acvm::acir::circuit::{Circuit, Opcode, OpcodeLocation}; use acvm::acir::native_types::{Witness, WitnessMap}; use acvm::{BlackBoxFunctionSolver, FieldElement}; @@ -20,6 +21,7 @@ pub struct ReplDebugger<'a, B: BlackBoxFunctionSolver> { debug_artifact: &'a DebugArtifact, initial_witness: WitnessMap, last_result: DebugCommandResult, + unconstrained_functions: &'a [BrilligBytecode], } impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { @@ -28,6 +30,7 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { circuit: &'a Circuit, debug_artifact: &'a DebugArtifact, initial_witness: WitnessMap, + unconstrained_functions: &'a [BrilligBytecode], ) -> Self { let foreign_call_executor = Box::new(DefaultDebugForeignCallExecutor::from_artifact(true, debug_artifact)); @@ -37,6 +40,7 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { debug_artifact, initial_witness.clone(), foreign_call_executor, + unconstrained_functions, ); let last_result = if context.get_current_opcode_location().is_none() { // handle circuit with no opcodes @@ -44,7 +48,7 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { } else { DebugCommandResult::Ok }; - Self { context, blackbox_solver, circuit, debug_artifact, initial_witness, last_result } + Self { context, blackbox_solver, circuit, debug_artifact, initial_witness, last_result, unconstrained_functions } } pub fn show_current_vm_status(&self) { @@ -271,6 +275,7 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { self.debug_artifact, self.initial_witness.clone(), foreign_call_executor, + self.unconstrained_functions, ); for opcode_location in breakpoints { self.context.add_breakpoint(opcode_location); @@ -361,9 +366,10 @@ pub fn run( circuit: &Circuit, debug_artifact: &DebugArtifact, initial_witness: WitnessMap, + unconstrained_functions: &[BrilligBytecode], ) -> Result, NargoError> { let context = - RefCell::new(ReplDebugger::new(blackbox_solver, circuit, debug_artifact, initial_witness)); + RefCell::new(ReplDebugger::new(blackbox_solver, circuit, debug_artifact, initial_witness, unconstrained_functions)); let ref_context = &context; ref_context.borrow().show_current_vm_status(); diff --git a/noir/noir-repo/tooling/nargo/src/ops/execute.rs b/noir/noir-repo/tooling/nargo/src/ops/execute.rs index 6d328d65119b..c25e7d3563ea 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/execute.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/execute.rs @@ -1,3 +1,4 @@ +use acvm::acir::circuit::brillig::BrilligBytecode; use acvm::acir::circuit::Program; use acvm::acir::native_types::WitnessStack; use acvm::brillig_vm::brillig::ForeignCallResult; @@ -12,6 +13,9 @@ use super::foreign_calls::{ForeignCallExecutor, NargoForeignCallResult}; struct ProgramExecutor<'a, B: BlackBoxFunctionSolver, F: ForeignCallExecutor> { functions: &'a [Circuit], + + unconstrained_functions: &'a [BrilligBytecode], + // This gets built as we run through the program looking at each function call witness_stack: WitnessStack, @@ -23,11 +27,13 @@ struct ProgramExecutor<'a, B: BlackBoxFunctionSolver, F: ForeignCallExecutor> { impl<'a, B: BlackBoxFunctionSolver, F: ForeignCallExecutor> ProgramExecutor<'a, B, F> { fn new( functions: &'a [Circuit], + unconstrained_functions: &'a [BrilligBytecode], blackbox_solver: &'a B, foreign_call_executor: &'a mut F, ) -> Self { ProgramExecutor { functions, + unconstrained_functions, witness_stack: WitnessStack::default(), blackbox_solver, foreign_call_executor, @@ -44,7 +50,7 @@ impl<'a, B: BlackBoxFunctionSolver, F: ForeignCallExecutor> ProgramExecutor<'a, circuit: &Circuit, initial_witness: WitnessMap, ) -> Result { - let mut acvm = ACVM::new(self.blackbox_solver, &circuit.opcodes, initial_witness); + let mut acvm = ACVM::new(self.blackbox_solver, &circuit.opcodes, initial_witness, self.unconstrained_functions); // This message should be resolved by a nargo foreign call only when we have an unsatisfied assertion. let mut assert_message: Option = None; @@ -146,7 +152,7 @@ pub fn execute_program( let main = &program.functions[0]; let mut executor = - ProgramExecutor::new(&program.functions, blackbox_solver, foreign_call_executor); + ProgramExecutor::new(&program.functions, &program.unconstrained_functions, blackbox_solver, foreign_call_executor); let main_witness = executor.execute_circuit(main, initial_witness)?; executor.witness_stack.push(0, main_witness); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs index 4f3e2886b2e0..5a9a33c0acd9 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -242,6 +242,7 @@ pub(crate) fn debug_program( &compiled_program.program.functions[0], debug_artifact, initial_witness, + &compiled_program.program.unconstrained_functions, ) .map_err(CliError::from) } From 6bbd4f622e552df53e31b6e2ff3d1d1e3d561804 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 12 Apr 2024 14:04:25 +0000 Subject: [PATCH 03/47] update circuit serialization and instance deployer constant --- .../acir/tests/test_program_serialization.rs | 113 +++++++++--------- .../acvm-repo/acvm_js/test/shared/addition.ts | 10 +- .../test/shared/complex_foreign_call.ts | 14 +-- .../test/shared/fixed_base_scalar_mul.ts | 6 +- .../acvm_js/test/shared/foreign_call.ts | 8 +- .../acvm_js/test/shared/memory_op.ts | 8 +- .../acvm_js/test/shared/nested_acir_call.ts | 14 +-- .../acvm-repo/acvm_js/test/shared/pedersen.ts | 4 +- .../acvm_js/test/shared/schnorr_verify.ts | 24 ++-- yarn-project/circuits.js/src/constants.gen.ts | 2 +- 10 files changed, 102 insertions(+), 101 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs index c067ee87b7b4..12c5565ede96 100644 --- a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs +++ b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs @@ -46,12 +46,12 @@ fn addition_circuit() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 75, 14, 128, 32, 12, 68, 249, 120, 160, 150, - 182, 208, 238, 188, 138, 68, 184, 255, 17, 212, 200, 130, 196, 165, 188, 164, 153, 174, 94, - 38, 227, 221, 203, 118, 159, 119, 95, 226, 200, 125, 36, 252, 3, 253, 66, 87, 152, 92, 4, - 153, 185, 149, 212, 144, 240, 128, 100, 85, 5, 88, 106, 86, 84, 20, 149, 51, 41, 81, 83, - 214, 98, 213, 10, 24, 50, 53, 236, 98, 212, 135, 44, 174, 235, 5, 143, 35, 12, 151, 159, - 126, 55, 109, 28, 231, 145, 47, 245, 105, 191, 143, 133, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 65, 14, 128, 32, 12, 4, 65, 124, 80, 75, 91, + 104, 111, 126, 69, 34, 252, 255, 9, 106, 228, 64, 162, 55, 153, 164, 217, 158, 38, 155, + 245, 238, 97, 189, 206, 187, 55, 161, 231, 214, 19, 254, 129, 126, 162, 107, 25, 92, 4, + 137, 185, 230, 88, 145, 112, 135, 104, 69, 5, 88, 74, 82, 84, 20, 149, 35, 42, 81, 85, 214, + 108, 197, 50, 24, 50, 85, 108, 98, 212, 186, 44, 204, 235, 5, 183, 99, 233, 46, 63, 252, + 110, 216, 56, 184, 15, 78, 146, 74, 173, 20, 141, 1, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -77,9 +77,9 @@ fn fixed_base_scalar_mul_circuit() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 138, 81, 10, 0, 48, 8, 66, 87, 219, 190, 118, 233, - 29, 61, 43, 3, 5, 121, 34, 207, 86, 231, 162, 198, 157, 124, 228, 71, 157, 220, 232, 161, - 227, 226, 206, 214, 95, 221, 74, 0, 116, 58, 13, 182, 105, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 85, 138, 81, 10, 0, 48, 8, 66, 87, 219, 190, 118, 233, + 29, 61, 35, 3, 19, 228, 137, 60, 91, 149, 139, 26, 119, 242, 145, 31, 117, 114, 163, 135, + 142, 139, 219, 91, 127, 117, 71, 2, 117, 84, 50, 98, 113, 0, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -105,9 +105,9 @@ fn pedersen_circuit() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 7, 6, 0, 0, 8, 108, 209, 255, 63, 156, 54, 233, - 56, 55, 17, 26, 18, 196, 241, 169, 250, 178, 141, 167, 32, 159, 254, 234, 238, 255, 87, - 112, 52, 63, 63, 101, 105, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 9, 10, 0, 0, 4, 115, 149, 255, 127, 88, 8, 133, + 213, 218, 137, 80, 144, 32, 182, 79, 213, 151, 173, 61, 5, 121, 245, 91, 103, 255, 191, 3, + 7, 16, 26, 112, 158, 113, 0, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -147,22 +147,22 @@ fn schnorr_verify_circuit() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 7, 78, 2, 1, 20, 69, 81, 236, 189, 247, 222, - 123, 239, 93, 177, 33, 34, 238, 194, 253, 47, 193, 200, 147, 67, 194, 36, 147, 163, 33, 33, - 228, 191, 219, 82, 168, 63, 63, 181, 183, 197, 223, 177, 147, 191, 181, 183, 149, 69, 159, - 183, 213, 222, 238, 218, 219, 206, 14, 118, 178, 139, 141, 183, 135, 189, 236, 99, 63, 7, - 56, 200, 33, 14, 115, 132, 163, 28, 227, 56, 39, 56, 201, 41, 78, 115, 134, 179, 156, 227, - 60, 23, 184, 200, 37, 46, 115, 133, 171, 92, 227, 58, 55, 184, 201, 45, 110, 115, 135, 187, - 220, 227, 62, 15, 120, 200, 35, 30, 243, 132, 167, 60, 227, 57, 47, 120, 201, 43, 94, 243, - 134, 183, 188, 227, 61, 31, 248, 200, 39, 22, 249, 204, 151, 166, 29, 243, 188, 250, 255, - 141, 239, 44, 241, 131, 101, 126, 178, 194, 47, 86, 249, 237, 123, 171, 76, 127, 105, 47, - 189, 165, 181, 116, 150, 198, 26, 125, 245, 248, 45, 233, 41, 45, 165, 163, 52, 148, 126, - 210, 78, 186, 73, 51, 233, 37, 173, 164, 147, 52, 146, 62, 210, 70, 186, 72, 19, 233, 33, - 45, 164, 131, 52, 144, 253, 151, 11, 245, 221, 179, 121, 246, 206, 214, 217, 57, 27, 103, - 223, 109, 187, 238, 218, 115, 223, 142, 135, 246, 59, 182, 219, 169, 189, 206, 237, 116, - 105, 159, 107, 187, 220, 218, 227, 222, 14, 143, 238, 95, 116, 247, 23, 119, 126, 115, 223, - 146, 187, 150, 221, 179, 226, 142, 141, 155, 53, 238, 86, 104, 186, 231, 255, 243, 7, 100, - 141, 232, 192, 233, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 85, 210, 135, 74, 66, 1, 24, 134, 97, 219, 123, 239, + 189, 247, 222, 187, 108, 153, 153, 221, 69, 247, 127, 9, 145, 31, 62, 130, 29, 56, 60, 133, + 32, 242, 127, 111, 75, 161, 254, 252, 212, 222, 22, 127, 199, 78, 254, 214, 222, 86, 22, + 125, 222, 86, 123, 187, 107, 111, 59, 59, 216, 201, 46, 54, 222, 30, 246, 178, 143, 253, + 28, 224, 32, 135, 56, 204, 17, 142, 114, 140, 227, 156, 224, 36, 167, 56, 205, 25, 206, + 114, 142, 243, 92, 224, 34, 151, 184, 204, 21, 174, 114, 141, 235, 220, 224, 38, 183, 184, + 205, 29, 238, 114, 143, 251, 60, 224, 33, 143, 120, 204, 19, 158, 242, 140, 231, 188, 224, + 37, 175, 120, 205, 27, 222, 242, 142, 247, 124, 224, 35, 159, 88, 228, 51, 95, 154, 118, + 204, 243, 234, 255, 55, 190, 179, 196, 15, 150, 249, 201, 10, 191, 88, 229, 183, 239, 173, + 50, 253, 165, 189, 244, 150, 214, 210, 89, 26, 107, 244, 213, 227, 183, 164, 167, 180, 148, + 142, 210, 80, 250, 73, 59, 233, 38, 205, 164, 151, 180, 146, 78, 210, 72, 250, 72, 27, 233, + 34, 77, 164, 135, 180, 144, 14, 210, 64, 246, 95, 46, 212, 119, 207, 230, 217, 59, 91, 103, + 231, 108, 156, 125, 183, 237, 186, 107, 207, 125, 59, 30, 218, 239, 216, 110, 167, 246, 58, + 183, 211, 165, 125, 174, 237, 114, 107, 143, 123, 59, 60, 186, 127, 209, 221, 95, 220, 249, + 205, 125, 75, 238, 90, 118, 207, 138, 59, 54, 110, 214, 184, 91, 161, 233, 158, 255, 158, + 63, 46, 139, 64, 203, 241, 3, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -211,11 +211,12 @@ fn simple_brillig_foreign_call() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 61, 10, 192, 48, 8, 133, 53, 133, 82, 186, - 245, 38, 233, 13, 122, 153, 14, 93, 58, 132, 144, 227, 135, 252, 41, 56, 36, 46, 201, 7, - 162, 168, 200, 123, 34, 52, 142, 28, 72, 245, 38, 106, 9, 247, 30, 202, 118, 142, 27, 215, - 221, 178, 82, 175, 33, 15, 133, 189, 163, 159, 57, 197, 252, 251, 195, 235, 188, 230, 186, - 16, 65, 255, 12, 239, 92, 131, 89, 149, 198, 77, 3, 10, 9, 119, 8, 198, 242, 152, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 61, 10, 192, 32, 12, 133, 19, 11, 165, 116, + 235, 77, 236, 13, 122, 153, 14, 93, 58, 136, 120, 124, 241, 47, 129, 12, 42, 130, 126, 16, + 18, 146, 16, 222, 11, 66, 225, 136, 129, 84, 111, 162, 150, 112, 239, 161, 172, 231, 184, + 113, 221, 45, 45, 245, 42, 242, 144, 216, 43, 250, 153, 83, 204, 191, 223, 189, 198, 246, + 92, 39, 60, 244, 63, 195, 59, 87, 99, 150, 165, 113, 83, 193, 0, 1, 19, 247, 29, 5, 160, 1, + 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -311,15 +312,15 @@ fn complex_brillig_foreign_call() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 93, 10, 131, 48, 12, 78, 218, 233, 100, 111, - 187, 193, 96, 59, 64, 231, 9, 188, 139, 248, 166, 232, 163, 167, 23, 11, 126, 197, 24, 250, - 34, 86, 208, 64, 72, 218, 252, 125, 36, 105, 153, 22, 42, 60, 51, 116, 235, 217, 64, 103, - 156, 37, 5, 191, 10, 210, 29, 163, 63, 167, 203, 229, 206, 194, 104, 110, 128, 209, 158, - 128, 49, 236, 195, 69, 231, 157, 114, 46, 73, 251, 103, 35, 239, 231, 225, 57, 243, 156, - 227, 252, 132, 44, 112, 79, 176, 125, 84, 223, 73, 248, 145, 152, 69, 149, 4, 107, 233, - 114, 90, 119, 145, 85, 237, 151, 192, 89, 247, 221, 208, 54, 163, 85, 174, 26, 234, 87, - 232, 63, 101, 103, 21, 55, 169, 216, 73, 72, 249, 5, 197, 234, 132, 123, 179, 35, 247, 155, - 214, 246, 102, 20, 73, 204, 72, 168, 123, 191, 161, 25, 66, 136, 159, 187, 53, 5, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 75, 10, 132, 48, 12, 77, 218, 209, 145, 217, + 205, 13, 6, 198, 3, 84, 79, 224, 93, 196, 157, 162, 75, 79, 47, 22, 124, 197, 16, 186, 17, + 43, 104, 32, 36, 109, 126, 143, 36, 45, 211, 70, 133, 103, 134, 110, 61, 27, 232, 140, 179, + 164, 224, 215, 64, 186, 115, 84, 113, 186, 92, 238, 42, 140, 230, 1, 24, 237, 5, 24, 195, + 62, 220, 116, 222, 41, 231, 146, 180, 127, 54, 242, 126, 94, 158, 51, 207, 57, 206, 111, + 200, 2, 247, 4, 219, 79, 245, 157, 132, 31, 137, 89, 52, 73, 176, 214, 46, 167, 125, 23, + 89, 213, 254, 8, 156, 237, 56, 76, 125, 55, 91, 229, 170, 161, 254, 133, 94, 42, 59, 171, + 184, 69, 197, 46, 66, 202, 47, 40, 86, 39, 220, 155, 3, 185, 191, 180, 183, 55, 163, 72, + 98, 70, 66, 221, 251, 40, 173, 255, 35, 68, 62, 61, 5, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -353,11 +354,11 @@ fn memory_op_circuit() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 81, 201, 13, 0, 32, 8, 147, 195, 125, 112, 3, 247, - 159, 74, 141, 60, 106, 226, 79, 120, 216, 132, 180, 124, 154, 82, 168, 108, 212, 57, 2, - 122, 129, 157, 201, 181, 150, 59, 186, 179, 189, 161, 101, 251, 82, 176, 175, 196, 121, 89, - 118, 185, 246, 91, 185, 26, 125, 187, 64, 80, 134, 29, 195, 31, 79, 24, 2, 250, 167, 252, - 27, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 144, 49, 14, 0, 32, 8, 3, 65, 196, 247, 224, 15, + 252, 255, 171, 52, 177, 3, 3, 155, 48, 120, 9, 41, 44, 77, 41, 211, 69, 207, 8, 246, 1, + 109, 80, 198, 174, 20, 179, 160, 246, 198, 172, 246, 229, 100, 95, 201, 243, 178, 234, 114, + 237, 183, 114, 123, 246, 239, 226, 130, 54, 119, 251, 240, 157, 2, 54, 249, 149, 243, 126, + 35, 3, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -456,15 +457,15 @@ fn nested_acir_call_circuit() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 205, 146, 97, 10, 195, 32, 12, 133, 163, 66, 207, 147, - 24, 173, 241, 223, 174, 50, 153, 189, 255, 17, 214, 177, 148, 89, 17, 250, 99, 14, 246, - 224, 97, 144, 16, 146, 143, 231, 224, 45, 167, 126, 105, 217, 109, 118, 91, 248, 200, 168, - 225, 248, 191, 106, 114, 208, 233, 104, 188, 233, 139, 223, 137, 108, 51, 139, 113, 13, - 161, 38, 95, 137, 233, 142, 62, 23, 137, 24, 98, 89, 133, 132, 162, 196, 135, 23, 230, 42, - 65, 82, 46, 57, 97, 166, 192, 149, 182, 152, 121, 211, 97, 110, 222, 94, 8, 13, 132, 182, - 54, 48, 144, 235, 8, 254, 10, 22, 76, 132, 101, 231, 237, 229, 23, 189, 213, 54, 119, 15, - 83, 212, 199, 172, 175, 79, 113, 51, 48, 198, 253, 207, 84, 13, 204, 141, 224, 21, 176, - 147, 158, 66, 231, 43, 145, 6, 4, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 205, 146, 65, 10, 3, 33, 12, 69, 163, 46, 230, 58, 137, + 209, 49, 238, 122, 149, 74, 157, 251, 31, 161, 83, 154, 161, 86, 132, 89, 212, 194, 124, + 248, 24, 36, 132, 228, 241, 29, 188, 229, 212, 47, 45, 187, 205, 110, 11, 31, 25, 53, 28, + 255, 103, 77, 14, 58, 29, 141, 55, 125, 241, 55, 145, 109, 102, 49, 174, 33, 212, 228, 43, + 49, 221, 209, 231, 34, 17, 67, 44, 171, 144, 80, 148, 248, 240, 194, 92, 37, 72, 202, 37, + 39, 204, 20, 184, 210, 22, 51, 111, 58, 204, 205, 219, 11, 161, 129, 208, 214, 6, 6, 114, + 29, 193, 127, 193, 130, 137, 176, 236, 188, 189, 252, 162, 183, 218, 230, 238, 97, 138, + 250, 152, 245, 245, 87, 220, 12, 140, 113, 95, 153, 170, 129, 185, 17, 60, 3, 54, 212, 19, + 104, 145, 195, 151, 14, 4, 0, 0, ]; assert_eq!(bytes, expected_serialization); } diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/addition.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/addition.ts index b56a42868787..820a415acf39 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/addition.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/addition.ts @@ -2,11 +2,11 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `addition_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 75, 14, 128, 32, 12, 68, 249, 120, 160, 150, 182, 208, 238, 188, 138, 68, - 184, 255, 17, 212, 200, 130, 196, 165, 188, 164, 153, 174, 94, 38, 227, 221, 203, 118, 159, 119, 95, 226, 200, 125, - 36, 252, 3, 253, 66, 87, 152, 92, 4, 153, 185, 149, 212, 144, 240, 128, 100, 85, 5, 88, 106, 86, 84, 20, 149, 51, 41, - 81, 83, 214, 98, 213, 10, 24, 50, 53, 236, 98, 212, 135, 44, 174, 235, 5, 143, 35, 12, 151, 159, 126, 55, 109, 28, - 231, 145, 47, 245, 105, 191, 143, 133, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 65, 14, 128, 32, 12, 4, 65, 124, 80, 75, 91, 104, 111, 126, 69, 34, 252, + 255, 9, 106, 228, 64, 162, 55, 153, 164, 217, 158, 38, 155, 245, 238, 97, 189, 206, 187, 55, 161, 231, 214, 19, 254, + 129, 126, 162, 107, 25, 92, 4, 137, 185, 230, 88, 145, 112, 135, 104, 69, 5, 88, 74, 82, 84, 20, 149, 35, 42, 81, 85, + 214, 108, 197, 50, 24, 50, 85, 108, 98, 212, 186, 44, 204, 235, 5, 183, 99, 233, 46, 63, 252, 110, 216, 56, 184, 15, + 78, 146, 74, 173, 20, 141, 1, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts index e074cf1ad384..722bae8e015b 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts @@ -2,13 +2,13 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `complex_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 93, 10, 131, 48, 12, 78, 218, 233, 100, 111, 187, 193, 96, 59, 64, 231, 9, - 188, 139, 248, 166, 232, 163, 167, 23, 11, 126, 197, 24, 250, 34, 86, 208, 64, 72, 218, 252, 125, 36, 105, 153, 22, - 42, 60, 51, 116, 235, 217, 64, 103, 156, 37, 5, 191, 10, 210, 29, 163, 63, 167, 203, 229, 206, 194, 104, 110, 128, - 209, 158, 128, 49, 236, 195, 69, 231, 157, 114, 46, 73, 251, 103, 35, 239, 231, 225, 57, 243, 156, 227, 252, 132, 44, - 112, 79, 176, 125, 84, 223, 73, 248, 145, 152, 69, 149, 4, 107, 233, 114, 90, 119, 145, 85, 237, 151, 192, 89, 247, - 221, 208, 54, 163, 85, 174, 26, 234, 87, 232, 63, 101, 103, 21, 55, 169, 216, 73, 72, 249, 5, 197, 234, 132, 123, 179, - 35, 247, 155, 214, 246, 102, 20, 73, 204, 72, 168, 123, 191, 161, 25, 66, 136, 159, 187, 53, 5, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 75, 10, 132, 48, 12, 77, 218, 209, 145, 217, 205, 13, 6, 198, 3, 84, 79, + 224, 93, 196, 157, 162, 75, 79, 47, 22, 124, 197, 16, 186, 17, 43, 104, 32, 36, 109, 126, 143, 36, 45, 211, 70, 133, + 103, 134, 110, 61, 27, 232, 140, 179, 164, 224, 215, 64, 186, 115, 84, 113, 186, 92, 238, 42, 140, 230, 1, 24, 237, 5, + 24, 195, 62, 220, 116, 222, 41, 231, 146, 180, 127, 54, 242, 126, 94, 158, 51, 207, 57, 206, 111, 200, 2, 247, 4, 219, + 79, 245, 157, 132, 31, 137, 89, 52, 73, 176, 214, 46, 167, 125, 23, 89, 213, 254, 8, 156, 237, 56, 76, 125, 55, 91, + 229, 170, 161, 254, 133, 94, 42, 59, 171, 184, 69, 197, 46, 66, 202, 47, 40, 86, 39, 220, 155, 3, 185, 191, 180, 183, + 55, 163, 72, 98, 70, 66, 221, 251, 40, 173, 255, 35, 68, 62, 61, 5, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts index 5aef521f2313..97b5041121a8 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts @@ -1,8 +1,8 @@ // See `fixed_base_scalar_mul_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 138, 81, 10, 0, 48, 8, 66, 87, 219, 190, 118, 233, 29, 61, 43, 3, 5, 121, 34, - 207, 86, 231, 162, 198, 157, 124, 228, 71, 157, 220, 232, 161, 227, 226, 206, 214, 95, 221, 74, 0, 116, 58, 13, 182, - 105, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 85, 138, 81, 10, 0, 48, 8, 66, 87, 219, 190, 118, 233, 29, 61, 35, 3, 19, 228, 137, + 60, 91, 149, 139, 26, 119, 242, 145, 31, 117, 114, 163, 135, 142, 139, 219, 91, 127, 117, 71, 2, 117, 84, 50, 98, 113, + 0, 0, 0, ]); export const initialWitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts index eb14cb2e9f1b..0e3d77f62a9e 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts @@ -2,10 +2,10 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `simple_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 61, 10, 192, 48, 8, 133, 53, 133, 82, 186, 245, 38, 233, 13, 122, 153, - 14, 93, 58, 132, 144, 227, 135, 252, 41, 56, 36, 46, 201, 7, 162, 168, 200, 123, 34, 52, 142, 28, 72, 245, 38, 106, 9, - 247, 30, 202, 118, 142, 27, 215, 221, 178, 82, 175, 33, 15, 133, 189, 163, 159, 57, 197, 252, 251, 195, 235, 188, 230, - 186, 16, 65, 255, 12, 239, 92, 131, 89, 149, 198, 77, 3, 10, 9, 119, 8, 198, 242, 152, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 61, 10, 192, 32, 12, 133, 19, 11, 165, 116, 235, 77, 236, 13, 122, 153, + 14, 93, 58, 136, 120, 124, 241, 47, 129, 12, 42, 130, 126, 16, 18, 146, 16, 222, 11, 66, 225, 136, 129, 84, 111, 162, + 150, 112, 239, 161, 172, 231, 184, 113, 221, 45, 45, 245, 42, 242, 144, 216, 43, 250, 153, 83, 204, 191, 223, 189, + 198, 246, 92, 39, 60, 244, 63, 195, 59, 87, 99, 150, 165, 113, 83, 193, 0, 1, 19, 247, 29, 5, 160, 1, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000005'], diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts index 1d0e06b3c8a8..6fd5e6a4019d 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts @@ -1,9 +1,9 @@ // See `memory_op_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 81, 201, 13, 0, 32, 8, 147, 195, 125, 112, 3, 247, 159, 74, 141, 60, 106, 226, - 79, 120, 216, 132, 180, 124, 154, 82, 168, 108, 212, 57, 2, 122, 129, 157, 201, 181, 150, 59, 186, 179, 189, 161, 101, - 251, 82, 176, 175, 196, 121, 89, 118, 185, 246, 91, 185, 26, 125, 187, 64, 80, 134, 29, 195, 31, 79, 24, 2, 250, 167, - 252, 27, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 144, 49, 14, 0, 32, 8, 3, 65, 196, 247, 224, 15, 252, 255, 171, 52, 177, 3, 3, + 155, 48, 120, 9, 41, 44, 77, 41, 211, 69, 207, 8, 246, 1, 109, 80, 198, 174, 20, 179, 160, 246, 198, 172, 246, 229, + 100, 95, 201, 243, 178, 234, 114, 237, 183, 114, 123, 246, 239, 226, 130, 54, 119, 251, 240, 157, 2, 54, 249, 149, + 243, 126, 35, 3, 0, 0, ]); export const initialWitnessMap = new Map([ diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/nested_acir_call.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/nested_acir_call.ts index 1b745ab6a79a..4b73d01bb011 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/nested_acir_call.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/nested_acir_call.ts @@ -2,13 +2,13 @@ import { WitnessMap, StackItem, WitnessStack } from '@noir-lang/acvm_js'; // See `nested_acir_call_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 205, 146, 97, 10, 195, 32, 12, 133, 163, 66, 207, 147, 24, 173, 241, 223, 174, 50, - 153, 189, 255, 17, 214, 177, 148, 89, 17, 250, 99, 14, 246, 224, 97, 144, 16, 146, 143, 231, 224, 45, 167, 126, 105, - 217, 109, 118, 91, 248, 200, 168, 225, 248, 191, 106, 114, 208, 233, 104, 188, 233, 139, 223, 137, 108, 51, 139, 113, - 13, 161, 38, 95, 137, 233, 142, 62, 23, 137, 24, 98, 89, 133, 132, 162, 196, 135, 23, 230, 42, 65, 82, 46, 57, 97, - 166, 192, 149, 182, 152, 121, 211, 97, 110, 222, 94, 8, 13, 132, 182, 54, 48, 144, 235, 8, 254, 10, 22, 76, 132, 101, - 231, 237, 229, 23, 189, 213, 54, 119, 15, 83, 212, 199, 172, 175, 79, 113, 51, 48, 198, 253, 207, 84, 13, 204, 141, - 224, 21, 176, 147, 158, 66, 231, 43, 145, 6, 4, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 205, 146, 65, 10, 3, 33, 12, 69, 163, 46, 230, 58, 137, 209, 49, 238, 122, 149, 74, + 157, 251, 31, 161, 83, 154, 161, 86, 132, 89, 212, 194, 124, 248, 24, 36, 132, 228, 241, 29, 188, 229, 212, 47, 45, + 187, 205, 110, 11, 31, 25, 53, 28, 255, 103, 77, 14, 58, 29, 141, 55, 125, 241, 55, 145, 109, 102, 49, 174, 33, 212, + 228, 43, 49, 221, 209, 231, 34, 17, 67, 44, 171, 144, 80, 148, 248, 240, 194, 92, 37, 72, 202, 37, 39, 204, 20, 184, + 210, 22, 51, 111, 58, 204, 205, 219, 11, 161, 129, 208, 214, 6, 6, 114, 29, 193, 127, 193, 130, 137, 176, 236, 188, + 189, 252, 162, 183, 218, 230, 238, 97, 138, 250, 152, 245, 245, 87, 220, 12, 140, 113, 95, 153, 170, 129, 185, 17, 60, + 3, 54, 212, 19, 104, 145, 195, 151, 14, 4, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts index 00d207053d89..e8ddc893d879 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts @@ -1,7 +1,7 @@ // See `pedersen_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 7, 6, 0, 0, 8, 108, 209, 255, 63, 156, 54, 233, 56, 55, 17, 26, 18, 196, - 241, 169, 250, 178, 141, 167, 32, 159, 254, 234, 238, 255, 87, 112, 52, 63, 63, 101, 105, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 9, 10, 0, 0, 4, 115, 149, 255, 127, 88, 8, 133, 213, 218, 137, 80, 144, 32, + 182, 79, 213, 151, 173, 61, 5, 121, 245, 91, 103, 255, 191, 3, 7, 16, 26, 112, 158, 113, 0, 0, 0, ]); export const initialWitnessMap = new Map([[1, '0x0000000000000000000000000000000000000000000000000000000000000001']]); diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/schnorr_verify.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/schnorr_verify.ts index 14c32c615c81..0aef82bc8e93 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/schnorr_verify.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/schnorr_verify.ts @@ -1,17 +1,17 @@ // See `schnorr_verify_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 7, 78, 2, 1, 20, 69, 81, 236, 189, 247, 222, 123, 239, 93, 177, 33, 34, - 238, 194, 253, 47, 193, 200, 147, 67, 194, 36, 147, 163, 33, 33, 228, 191, 219, 82, 168, 63, 63, 181, 183, 197, 223, - 177, 147, 191, 181, 183, 149, 69, 159, 183, 213, 222, 238, 218, 219, 206, 14, 118, 178, 139, 141, 183, 135, 189, 236, - 99, 63, 7, 56, 200, 33, 14, 115, 132, 163, 28, 227, 56, 39, 56, 201, 41, 78, 115, 134, 179, 156, 227, 60, 23, 184, - 200, 37, 46, 115, 133, 171, 92, 227, 58, 55, 184, 201, 45, 110, 115, 135, 187, 220, 227, 62, 15, 120, 200, 35, 30, - 243, 132, 167, 60, 227, 57, 47, 120, 201, 43, 94, 243, 134, 183, 188, 227, 61, 31, 248, 200, 39, 22, 249, 204, 151, - 166, 29, 243, 188, 250, 255, 141, 239, 44, 241, 131, 101, 126, 178, 194, 47, 86, 249, 237, 123, 171, 76, 127, 105, 47, - 189, 165, 181, 116, 150, 198, 26, 125, 245, 248, 45, 233, 41, 45, 165, 163, 52, 148, 126, 210, 78, 186, 73, 51, 233, - 37, 173, 164, 147, 52, 146, 62, 210, 70, 186, 72, 19, 233, 33, 45, 164, 131, 52, 144, 253, 151, 11, 245, 221, 179, - 121, 246, 206, 214, 217, 57, 27, 103, 223, 109, 187, 238, 218, 115, 223, 142, 135, 246, 59, 182, 219, 169, 189, 206, - 237, 116, 105, 159, 107, 187, 220, 218, 227, 222, 14, 143, 238, 95, 116, 247, 23, 119, 126, 115, 223, 146, 187, 150, - 221, 179, 226, 142, 141, 155, 53, 238, 86, 104, 186, 231, 255, 243, 7, 100, 141, 232, 192, 233, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 85, 210, 135, 74, 66, 1, 24, 134, 97, 219, 123, 239, 189, 247, 222, 187, 108, 153, + 153, 221, 69, 247, 127, 9, 145, 31, 62, 130, 29, 56, 60, 133, 32, 242, 127, 111, 75, 161, 254, 252, 212, 222, 22, 127, + 199, 78, 254, 214, 222, 86, 22, 125, 222, 86, 123, 187, 107, 111, 59, 59, 216, 201, 46, 54, 222, 30, 246, 178, 143, + 253, 28, 224, 32, 135, 56, 204, 17, 142, 114, 140, 227, 156, 224, 36, 167, 56, 205, 25, 206, 114, 142, 243, 92, 224, + 34, 151, 184, 204, 21, 174, 114, 141, 235, 220, 224, 38, 183, 184, 205, 29, 238, 114, 143, 251, 60, 224, 33, 143, 120, + 204, 19, 158, 242, 140, 231, 188, 224, 37, 175, 120, 205, 27, 222, 242, 142, 247, 124, 224, 35, 159, 88, 228, 51, 95, + 154, 118, 204, 243, 234, 255, 55, 190, 179, 196, 15, 150, 249, 201, 10, 191, 88, 229, 183, 239, 173, 50, 253, 165, + 189, 244, 150, 214, 210, 89, 26, 107, 244, 213, 227, 183, 164, 167, 180, 148, 142, 210, 80, 250, 73, 59, 233, 38, 205, + 164, 151, 180, 146, 78, 210, 72, 250, 72, 27, 233, 34, 77, 164, 135, 180, 144, 14, 210, 64, 246, 95, 46, 212, 119, + 207, 230, 217, 59, 91, 103, 231, 108, 156, 125, 183, 237, 186, 107, 207, 125, 59, 30, 218, 239, 216, 110, 167, 246, + 58, 183, 211, 165, 125, 174, 237, 114, 107, 143, 123, 59, 60, 186, 127, 209, 221, 95, 220, 249, 205, 125, 75, 238, 90, + 118, 207, 138, 59, 54, 110, 214, 184, 91, 161, 233, 158, 255, 158, 63, 46, 139, 64, 203, 241, 3, 0, 0, ]); export const initialWitnessMap = new Map([ diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 5a8cb29928c9..6317d29da10e 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 = 0x1df42e0457430b8d294d920181cc72ae0e3c5f8afd8d62d461bd26773cfdf3c1n; +export const DEPLOYER_CONTRACT_ADDRESS = 0x1d144e236f9df5ca2e46d274585f322f16502b33a91cd24bce24c93b73dde3c5n; 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; From b93a95f3cf4ae666c868c178fc731c9f3b68e8cf Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 12 Apr 2024 14:05:37 +0000 Subject: [PATCH 04/47] revert commented hash check --- noir/noir-repo/acvm-repo/acir/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acir/src/lib.rs b/noir/noir-repo/acvm-repo/acir/src/lib.rs index 29e588744781..d14159f34a16 100644 --- a/noir/noir-repo/acvm-repo/acir/src/lib.rs +++ b/noir/noir-repo/acvm-repo/acir/src/lib.rs @@ -85,10 +85,10 @@ mod reflection { generator.output(&mut source, ®istry).unwrap(); // Comment this out to write updated C++ code to file. - // if let Some(old_hash) = old_hash { - // let new_hash = fxhash::hash64(&source); - // assert_eq!(new_hash, old_hash, "Serialization format has changed"); - // } + if let Some(old_hash) = old_hash { + let new_hash = fxhash::hash64(&source); + assert_eq!(new_hash, old_hash, "Serialization format has changed"); + } write_to_file(&source, &path); } From ae724193576b857b78083dea3ed7f11af91bcd38 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 12 Apr 2024 14:06:37 +0000 Subject: [PATCH 05/47] update todo comment --- noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs index 7c936f98fd59..19470f9292cb 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs @@ -289,7 +289,7 @@ fn count_opcodes_and_gates_in_program( Ok(FunctionInfo { name: compiled_program.names[i].clone(), acir_opcodes: function.opcodes.len(), - // TODO: update serialization on backend. Unconstrained funcs will not matter here though + // Unconstrained functions do not matter to a backend circuit count so we pass nothing here circuit_size: backend.get_exact_circuit_size(&Program { functions: vec![function], unconstrained_functions: vec![], From 375f9f64bc17acdf7f40fd89a3fb6a280955c982 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 12 Apr 2024 15:46:10 +0000 Subject: [PATCH 06/47] handle brillig pointer in acvm js and cargo fmt --- noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs | 37 ++++++++++++------- .../acvm-repo/acvm_js/src/execute.rs | 25 +++++++++++-- .../compiler/noirc_evaluator/src/ssa.rs | 9 ++--- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 8 +++- .../ssa/acir_gen/acir_ir/generated_acir.rs | 12 ++++-- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 16 +++++--- .../src/ssa/ssa_gen/program.rs | 7 ++-- .../noir-repo/tooling/debugger/src/context.rs | 7 +++- noir/noir-repo/tooling/debugger/src/dap.rs | 2 +- noir/noir-repo/tooling/debugger/src/lib.rs | 2 +- noir/noir-repo/tooling/debugger/src/repl.rs | 19 ++++++++-- .../tooling/nargo/src/ops/execute.rs | 15 ++++++-- 12 files changed, 115 insertions(+), 44 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index 82a8b3d5fabd..60920482a117 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -4,7 +4,11 @@ use std::collections::HashMap; use acir::{ brillig::ForeignCallResult, - circuit::{brillig::{Brillig, BrilligBytecode}, opcodes::BlockId, Opcode, OpcodeLocation}, + circuit::{ + brillig::{Brillig, BrilligBytecode}, + opcodes::BlockId, + Opcode, OpcodeLocation, + }, native_types::{Expression, Witness, WitnessMap}, BlackBoxFunc, FieldElement, }; @@ -167,15 +171,20 @@ pub struct ACVM<'a, B: BlackBoxFunctionSolver> { acir_call_results: Vec>, // A counter maintained through an ACVM process that determines - // whether the caller has resolved the bytecode of a Brillig pointer + // whether the caller has resolved the bytecode of a Brillig pointer // brillig_call_counter: usize, - // Represents the bytecode pointer + // Represents the bytecode pointer // brillig_bytecodes: Vec< unconstrained_functions: &'a [BrilligBytecode], } impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { - pub fn new(backend: &'a B, opcodes: &'a [Opcode], initial_witness: WitnessMap, unconstrained_functions: &'a [BrilligBytecode]) -> Self { + pub fn new( + backend: &'a B, + opcodes: &'a [Opcode], + initial_witness: WitnessMap, + unconstrained_functions: &'a [BrilligBytecode], + ) -> Self { let status = if opcodes.is_empty() { ACVMStatus::Solved } else { ACVMStatus::InProgress }; ACVM { status, @@ -188,7 +197,7 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { brillig_solver: None, acir_call_counter: 0, acir_call_results: Vec::default(), - unconstrained_functions + unconstrained_functions, } } @@ -390,7 +399,8 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { let witness = &mut self.witness_map; if is_predicate_false(witness, &brillig.predicate)? { - return BrilligSolver::::zero_out_brillig_outputs(witness, &brillig.outputs).map(|_| None); + return BrilligSolver::::zero_out_brillig_outputs(witness, &brillig.outputs) + .map(|_| None); } // If we're resuming execution after resolving a foreign call then @@ -425,29 +435,29 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { fn solve_brillig_pointer_opcode( &mut self, ) -> Result, OpcodeResolutionError> { - let Opcode::BrilligPointer(brillig_pointer) = &self.opcodes[self.instruction_pointer] else { + let Opcode::BrilligPointer(brillig_pointer) = &self.opcodes[self.instruction_pointer] + else { unreachable!("Not executing a Brillig opcode"); }; let witness = &mut self.witness_map; if is_predicate_false(witness, &brillig_pointer.predicate)? { - return BrilligSolver::::zero_out_brillig_outputs(witness, &brillig_pointer.outputs).map(|_| None); + return BrilligSolver::::zero_out_brillig_outputs(witness, &brillig_pointer.outputs) + .map(|_| None); } // If we're resuming execution after resolving a foreign call then // there will be a cached `BrilligSolver` to avoid recomputation. let mut solver: BrilligSolver<'_, B> = match self.brillig_solver.take() { Some(solver) => solver, - None => { - BrilligSolver::new_with_pointer( + None => BrilligSolver::new_with_pointer( witness, &self.block_solvers, brillig_pointer, &self.unconstrained_functions[brillig_pointer.bytecode_index as usize].bytecode, self.backend, self.instruction_pointer, - )? - } + )?, }; match solver.solve()? { BrilligSolverStatus::ForeignCallWait(foreign_call) => { @@ -478,7 +488,8 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { }; if should_skip { - let resolution = BrilligSolver::::zero_out_brillig_outputs(witness, &brillig.outputs); + let resolution = + BrilligSolver::::zero_out_brillig_outputs(witness, &brillig.outputs); return StepResult::Status(self.handle_opcode_resolution(resolution)); } diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs b/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs index c97b8ea1a665..c516bb61a760 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs @@ -1,5 +1,6 @@ use std::{future::Future, pin::Pin}; +use acvm::acir::circuit::brillig::BrilligBytecode; use acvm::BlackBoxFunctionSolver; use acvm::{ acir::circuit::{Circuit, Program}, @@ -181,7 +182,12 @@ async fn execute_program_with_native_program_and_return( initial_witness: JsWitnessMap, foreign_call_executor: &ForeignCallHandler, ) -> Result { - let executor = ProgramExecutor::new(&program.functions, &solver.0, foreign_call_executor); + let executor = ProgramExecutor::new( + &program.functions, + &program.unconstrained_functions, + &solver.0, + foreign_call_executor, + ); let witness_stack = executor.execute(initial_witness.into()).await?; Ok(witness_stack) @@ -190,6 +196,8 @@ async fn execute_program_with_native_program_and_return( struct ProgramExecutor<'a, B: BlackBoxFunctionSolver> { functions: &'a [Circuit], + unconstrained_functions: &'a [BrilligBytecode], + blackbox_solver: &'a B, foreign_call_handler: &'a ForeignCallHandler, @@ -198,10 +206,16 @@ struct ProgramExecutor<'a, B: BlackBoxFunctionSolver> { impl<'a, B: BlackBoxFunctionSolver> ProgramExecutor<'a, B> { fn new( functions: &'a [Circuit], + unconstrained_functions: &'a [BrilligBytecode], blackbox_solver: &'a B, foreign_call_handler: &'a ForeignCallHandler, ) -> Self { - ProgramExecutor { functions, blackbox_solver, foreign_call_handler } + ProgramExecutor { + functions, + unconstrained_functions, + blackbox_solver, + foreign_call_handler, + } } async fn execute(&self, initial_witness: WitnessMap) -> Result { @@ -220,7 +234,12 @@ impl<'a, B: BlackBoxFunctionSolver> ProgramExecutor<'a, B> { witness_stack: &'a mut WitnessStack, ) -> Pin> + 'a>> { Box::pin(async { - let mut acvm = ACVM::new(self.blackbox_solver, &circuit.opcodes, initial_witness); + let mut acvm = ACVM::new( + self.blackbox_solver, + &circuit.opcodes, + initial_witness, + self.unconstrained_functions, + ); loop { let solver_status = acvm.solve(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index b43c22101ade..0c9b51a5b15c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -14,7 +14,9 @@ use crate::{ errors::{RuntimeError, SsaReport}, }; use acvm::acir::{ - circuit::{brillig::BrilligBytecode, Circuit, ExpressionWidth, Program as AcirProgram, PublicInputs}, + circuit::{ + brillig::BrilligBytecode, Circuit, ExpressionWidth, Program as AcirProgram, PublicInputs, + }, native_types::Witness, }; @@ -100,10 +102,7 @@ pub struct SsaProgramArtifact { impl SsaProgramArtifact { fn new(unconstrained_functions: Vec) -> Self { - let program = AcirProgram { - functions: Vec::default(), - unconstrained_functions, - }; + let program = AcirProgram { functions: Vec::default(), unconstrained_functions }; Self { program, debug: Vec::default(), diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 79613e1e5d51..736e5418efad 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1610,7 +1610,13 @@ impl AcirContext { }); let predicate = self.var_to_expression(predicate)?; - self.acir_ir.brillig_pointer(Some(predicate), &generated_brillig, b_inputs, b_outputs, brillig_function_index); + self.acir_ir.brillig_pointer( + Some(predicate), + &generated_brillig, + b_inputs, + b_outputs, + brillig_function_index, + ); fn range_constraint_value( context: &mut AcirContext, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index 725dde575ac9..9aa538e56081 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -576,7 +576,7 @@ impl GeneratedAcir { brillig_function_index: u32, ) { let opcode = AcirOpcode::BrilligPointer(BrilligPointer { - inputs, + inputs, outputs, bytecode_index: brillig_function_index, predicate, @@ -584,13 +584,19 @@ impl GeneratedAcir { self.push_opcode(opcode); for (brillig_index, call_stack) in generated_brillig.locations.iter() { self.locations.insert( - OpcodeLocation::Brillig { acir_index: self.opcodes.len() - 1, brillig_index: *brillig_index }, + OpcodeLocation::Brillig { + acir_index: self.opcodes.len() - 1, + brillig_index: *brillig_index, + }, call_stack.clone(), ); } for (brillig_index, message) in generated_brillig.assert_messages.iter() { self.assert_messages.insert( - OpcodeLocation::Brillig { acir_index: self.opcodes.len() - 1, brillig_index: *brillig_index }, + OpcodeLocation::Brillig { + acir_index: self.opcodes.len() - 1, + brillig_index: *brillig_index, + }, message.clone(), ); } 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 787d54f96330..b0a91ed2a1f9 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 @@ -94,7 +94,7 @@ struct Context<'a> { data_bus: DataBus, // TODO: could make this a Vec as the IDs have already made to be consecutive indices - generated_brillig_map: &'a mut HashMap + generated_brillig_map: &'a mut HashMap, } #[derive(Clone)] @@ -199,9 +199,12 @@ impl Ssa { acirs.push(generated_acir); } } - + // TODO: can just store the Brillig bytecode as we utilize the locations when setting acir locations - let brilligs = generated_brillig_map.iter().map(|(_, brillig)| BrilligBytecode { bytecode: brillig.byte_code.clone() }).collect::>(); + let brilligs = generated_brillig_map + .iter() + .map(|(_, brillig)| BrilligBytecode { bytecode: brillig.byte_code.clone() }) + .collect::>(); // TODO: check whether doing this for a single circuit's return witnesses is correct. // We probably need it for all foldable circuits, as any circuit being folded is essentially an entry point. However, I do not know how that @@ -226,8 +229,7 @@ impl Ssa { main_func_acir.return_witnesses = distinct_return_witness; // Ok(acirs) } - Distinctness::DuplicationAllowed => {} - // Distinctness::DuplicationAllowed => Ok(acirs), + Distinctness::DuplicationAllowed => {} // Distinctness::DuplicationAllowed => Ok(acirs), } Ok((acirs, brilligs)) } @@ -639,7 +641,9 @@ impl<'a> Context<'a> { dfg.type_of_value(*result_id).into() }); - let output_values = if let Some(code) = self.generated_brillig_map.get(brillig_program_id) { + let output_values = if let Some(code) = + self.generated_brillig_map.get(brillig_program_id) + { dbg!("got previous generated brillig"); self.acir_context.brillig_pointer( self.current_side_effects_enabled_var, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs index 0c8093ceee7f..e5ead5384712 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs @@ -29,8 +29,8 @@ impl Ssa { let mut acir_index = 0; let mut brillig_index = 0; - let id_to_index = btree_map(functions.iter().enumerate(), |(i, (id, func))| { - match func.runtime() { + let id_to_index = + btree_map(functions.iter().enumerate(), |(i, (id, func))| match func.runtime() { RuntimeType::Acir(_) => { let res = (*id, acir_index); acir_index += 1; @@ -41,8 +41,7 @@ impl Ssa { brillig_index += 1; res } - } - }); + }); Self { functions, main_id, next_id: AtomicCounter::starting_after(max_id), id_to_index } } diff --git a/noir/noir-repo/tooling/debugger/src/context.rs b/noir/noir-repo/tooling/debugger/src/context.rs index 8f7cf8dc9013..1b054a27ff0c 100644 --- a/noir/noir-repo/tooling/debugger/src/context.rs +++ b/noir/noir-repo/tooling/debugger/src/context.rs @@ -48,7 +48,12 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { let source_to_opcodes = build_source_to_opcode_debug_mappings(debug_artifact); Self { // TODO: need to handle brillig in the debugger - acvm: ACVM::new(blackbox_solver, &circuit.opcodes, initial_witness, unconstrained_functions), + acvm: ACVM::new( + blackbox_solver, + &circuit.opcodes, + initial_witness, + unconstrained_functions, + ), brillig_solver: None, foreign_call_executor, debug_artifact, diff --git a/noir/noir-repo/tooling/debugger/src/dap.rs b/noir/noir-repo/tooling/debugger/src/dap.rs index 3f32cd8d809f..dc83337a9736 100644 --- a/noir/noir-repo/tooling/debugger/src/dap.rs +++ b/noir/noir-repo/tooling/debugger/src/dap.rs @@ -73,7 +73,7 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { debug_artifact, initial_witness, Box::new(DefaultDebugForeignCallExecutor::from_artifact(true, debug_artifact)), - unconstrained_functions + unconstrained_functions, ); Self { server, diff --git a/noir/noir-repo/tooling/debugger/src/lib.rs b/noir/noir-repo/tooling/debugger/src/lib.rs index c4bbd51b8b68..a8fc61c893f1 100644 --- a/noir/noir-repo/tooling/debugger/src/lib.rs +++ b/noir/noir-repo/tooling/debugger/src/lib.rs @@ -7,9 +7,9 @@ mod source_code_printer; use std::io::{Read, Write}; -use acvm::acir::circuit::brillig::BrilligBytecode; use ::dap::errors::ServerError; use ::dap::server::Server; +use acvm::acir::circuit::brillig::BrilligBytecode; use acvm::BlackBoxFunctionSolver; use acvm::{acir::circuit::Circuit, acir::native_types::WitnessMap}; diff --git a/noir/noir-repo/tooling/debugger/src/repl.rs b/noir/noir-repo/tooling/debugger/src/repl.rs index 9f175862bbb2..2a92698e5ce0 100644 --- a/noir/noir-repo/tooling/debugger/src/repl.rs +++ b/noir/noir-repo/tooling/debugger/src/repl.rs @@ -48,7 +48,15 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { } else { DebugCommandResult::Ok }; - Self { context, blackbox_solver, circuit, debug_artifact, initial_witness, last_result, unconstrained_functions } + Self { + context, + blackbox_solver, + circuit, + debug_artifact, + initial_witness, + last_result, + unconstrained_functions, + } } pub fn show_current_vm_status(&self) { @@ -368,8 +376,13 @@ pub fn run( initial_witness: WitnessMap, unconstrained_functions: &[BrilligBytecode], ) -> Result, NargoError> { - let context = - RefCell::new(ReplDebugger::new(blackbox_solver, circuit, debug_artifact, initial_witness, unconstrained_functions)); + let context = RefCell::new(ReplDebugger::new( + blackbox_solver, + circuit, + debug_artifact, + initial_witness, + unconstrained_functions, + )); let ref_context = &context; ref_context.borrow().show_current_vm_status(); diff --git a/noir/noir-repo/tooling/nargo/src/ops/execute.rs b/noir/noir-repo/tooling/nargo/src/ops/execute.rs index c25e7d3563ea..2a9bec86f310 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/execute.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/execute.rs @@ -50,7 +50,12 @@ impl<'a, B: BlackBoxFunctionSolver, F: ForeignCallExecutor> ProgramExecutor<'a, circuit: &Circuit, initial_witness: WitnessMap, ) -> Result { - let mut acvm = ACVM::new(self.blackbox_solver, &circuit.opcodes, initial_witness, self.unconstrained_functions); + let mut acvm = ACVM::new( + self.blackbox_solver, + &circuit.opcodes, + initial_witness, + self.unconstrained_functions, + ); // This message should be resolved by a nargo foreign call only when we have an unsatisfied assertion. let mut assert_message: Option = None; @@ -151,8 +156,12 @@ pub fn execute_program( ) -> Result { let main = &program.functions[0]; - let mut executor = - ProgramExecutor::new(&program.functions, &program.unconstrained_functions, blackbox_solver, foreign_call_executor); + let mut executor = ProgramExecutor::new( + &program.functions, + &program.unconstrained_functions, + blackbox_solver, + foreign_call_executor, + ); let main_witness = executor.execute_circuit(main, initial_witness)?; executor.witness_stack.push(0, main_witness); From e868e46cfbf02e8a83c15e9fe3e78551b17a6b2e Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 12 Apr 2024 16:08:05 +0000 Subject: [PATCH 07/47] cleanup BrilligSolver new methods --- .../acvm-repo/acvm/src/pwg/brillig.rs | 77 +++++++------------ noir/noir-repo/acvm-repo/acvm/tests/solver.rs | 27 +++---- .../src/ssa/ssa_gen/program.rs | 2 +- 3 files changed, 42 insertions(+), 64 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs index 9d16fddb857a..4fc12cdeef97 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs @@ -63,7 +63,7 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { Ok(()) } - // TODO: delete this old method + // TODO: Delete this old method once `Brillig` is deleted /// Constructs a solver for a Brillig block given the bytecode and initial /// witness. pub(crate) fn new( @@ -73,53 +73,13 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { bb_solver: &'b B, acir_index: usize, ) -> Result { - // Set input values - let mut calldata: Vec = Vec::new(); - // Each input represents an expression or array of expressions to evaluate. - // Iterate over each input and evaluate the expression(s) associated with it. - // Push the results into memory. - // If a certain expression is not solvable, we stall the ACVM and do not proceed with Brillig VM execution. - for input in &brillig.inputs { - match input { - BrilligInputs::Single(expr) => match get_value(expr, initial_witness) { - Ok(value) => calldata.push(value), - Err(_) => { - return Err(OpcodeResolutionError::OpcodeNotSolvable( - OpcodeNotSolvable::ExpressionHasTooManyUnknowns(expr.clone()), - )) - } - }, - BrilligInputs::Array(expr_arr) => { - // Attempt to fetch all array input values - for expr in expr_arr.iter() { - match get_value(expr, initial_witness) { - Ok(value) => calldata.push(value), - Err(_) => { - return Err(OpcodeResolutionError::OpcodeNotSolvable( - OpcodeNotSolvable::ExpressionHasTooManyUnknowns(expr.clone()), - )) - } - } - } - } - BrilligInputs::MemoryArray(block_id) => { - let memory_block = memory - .get(block_id) - .ok_or(OpcodeNotSolvable::MissingMemoryBlock(block_id.0))?; - for memory_index in 0..memory_block.block_len { - let memory_value = memory_block - .block_value - .get(&memory_index) - .expect("All memory is initialized on creation"); - calldata.push(*memory_value); - } - } - } - } - - // Instantiate a Brillig VM given the solved calldata - // along with the Brillig bytecode. - let vm = VM::new(calldata, &brillig.bytecode, vec![], bb_solver); + let vm = Self::setup_brillig_vm( + initial_witness, + memory, + &brillig.inputs, + &brillig.bytecode, + bb_solver + )?; Ok(Self { vm, acir_index }) } @@ -133,13 +93,30 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { bb_solver: &'b B, acir_index: usize, ) -> Result { + let vm = Self::setup_brillig_vm( + initial_witness, + memory, + &brillig_pointer.inputs, + brillig_bytecode, + bb_solver + )?; + Ok(Self { vm, acir_index }) + } + + fn setup_brillig_vm( + initial_witness: &WitnessMap, + memory: &HashMap, + inputs: &[BrilligInputs], + brillig_bytecode: &'b [BrilligOpcode], + bb_solver: &'b B, + ) -> Result, OpcodeResolutionError> { // Set input values let mut calldata: Vec = Vec::new(); // Each input represents an expression or array of expressions to evaluate. // Iterate over each input and evaluate the expression(s) associated with it. // Push the results into memory. // If a certain expression is not solvable, we stall the ACVM and do not proceed with Brillig VM execution. - for input in &brillig_pointer.inputs { + for input in inputs { match input { BrilligInputs::Single(expr) => match get_value(expr, initial_witness) { Ok(value) => calldata.push(value), @@ -180,7 +157,7 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { // Instantiate a Brillig VM given the solved calldata // along with the Brillig bytecode. let vm = VM::new(calldata, brillig_bytecode, vec![], bb_solver); - Ok(Self { vm, acir_index }) + Ok(vm) } pub fn get_memory(&self) -> &[MemoryValue] { diff --git a/noir/noir-repo/acvm-repo/acvm/tests/solver.rs b/noir/noir-repo/acvm-repo/acvm/tests/solver.rs index a708db5b0300..be24b59dc303 100644 --- a/noir/noir-repo/acvm-repo/acvm/tests/solver.rs +++ b/noir/noir-repo/acvm-repo/acvm/tests/solver.rs @@ -104,8 +104,8 @@ fn inversion_brillig_oracle_equivalence() { (Witness(2), FieldElement::from(3u128)), ]) .into(); - - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments); + let unconstrained_functions = vec![]; + let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments, &unconstrained_functions); // use the partial witness generation solver with our acir program let solver_status = acvm.solve(); @@ -241,8 +241,8 @@ fn double_inversion_brillig_oracle() { (Witness(9), FieldElement::from(10u128)), ]) .into(); - - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments); + let unconstrained_functions = vec![]; + let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments, &unconstrained_functions); // use the partial witness generation solver with our acir program let solver_status = acvm.solve(); @@ -370,8 +370,8 @@ fn oracle_dependent_execution() { let witness_assignments = BTreeMap::from([(w_x, FieldElement::from(2u128)), (w_y, FieldElement::from(2u128))]).into(); - - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments); + let unconstrained_functions = vec![]; + let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments, &unconstrained_functions); // use the partial witness generation solver with our acir program let solver_status = acvm.solve(); @@ -474,8 +474,8 @@ fn brillig_oracle_predicate() { (Witness(2), FieldElement::from(3u128)), ]) .into(); - - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments); + let unconstrained_functions = vec![]; + let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments, &unconstrained_functions); let solver_status = acvm.solve(); assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); @@ -509,7 +509,8 @@ fn unsatisfied_opcode_resolved() { values.insert(d, FieldElement::from(2_i128)); let opcodes = vec![Opcode::AssertZero(opcode_a)]; - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, values); + let unconstrained_functions = vec![]; + let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, values, &unconstrained_functions); let solver_status = acvm.solve(); assert_eq!( solver_status, @@ -591,8 +592,8 @@ fn unsatisfied_opcode_resolved_brillig() { values.insert(w_result, FieldElement::from(0_i128)); let opcodes = vec![brillig_opcode, Opcode::AssertZero(opcode_a)]; - - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, values); + let unconstrained_functions = vec![]; + let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, values, &unconstrained_functions); let solver_status = acvm.solve(); assert_eq!( solver_status, @@ -635,8 +636,8 @@ fn memory_operations() { }); let opcodes = vec![init, read_op, expression]; - - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, initial_witness); + let unconstrained_functions = vec![]; + let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, initial_witness, &unconstrained_functions); let solver_status = acvm.solve(); assert_eq!(solver_status, ACVMStatus::Solved); let witness_map = acvm.finalize(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs index e5ead5384712..a2eb3c03d998 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs @@ -30,7 +30,7 @@ impl Ssa { let mut acir_index = 0; let mut brillig_index = 0; let id_to_index = - btree_map(functions.iter().enumerate(), |(i, (id, func))| match func.runtime() { + btree_map(functions.iter().enumerate(), |(_, (id, func))| match func.runtime() { RuntimeType::Acir(_) => { let res = (*id, acir_index); acir_index += 1; From 3f58cf64dc26529fbed922dd472a4be11db06179 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 12 Apr 2024 16:13:28 +0000 Subject: [PATCH 08/47] some cleanup --- noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs | 11 +----- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 35 +++---------------- noir/noir-repo/cspell.json | 1 + .../noir-repo/tooling/debugger/src/context.rs | 2 +- 4 files changed, 7 insertions(+), 42 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index 60920482a117..fdec8bb14126 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -563,16 +563,7 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { self.acir_call_counter += 1; Ok(None) } - - // fn solve_brillig_pointer_opcode(&mut self) -> Result, OpcodeResolutionError> { - // if is_predicate_false(&self.witness_map, predicate)? { - // // Zero out the outputs if we have a false predicate - // for output in outputs { - // insert_value(output, FieldElement::zero(), &mut self.witness_map)?; - // } - // return Ok(None); - // } - // } + } // Returns the concrete value for a particular witness 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 b0a91ed2a1f9..d0f684b4c061 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 @@ -191,7 +191,7 @@ impl Ssa { let mut generated_brillig_map = HashMap::default(); for function in self.functions.values() { // let context = Context::new(); - let context = Context::new_with_brillig_map(&mut generated_brillig_map); + let context = Context::new(&mut generated_brillig_map); if let Some(mut generated_acir) = context.convert_ssa_function(&self, function, brillig)? { @@ -227,33 +227,15 @@ impl Ssa { .collect(); main_func_acir.return_witnesses = distinct_return_witness; - // Ok(acirs) } - Distinctness::DuplicationAllowed => {} // Distinctness::DuplicationAllowed => Ok(acirs), + Distinctness::DuplicationAllowed => {} } Ok((acirs, brilligs)) } } impl<'a> Context<'a> { - // fn new() -> Self { - // let mut acir_context = AcirContext::default(); - // let current_side_effects_enabled_var = acir_context.add_constant(FieldElement::one()); - // Context { - // ssa_values: HashMap::default(), - // current_side_effects_enabled_var, - // acir_context, - // initialized_arrays: HashSet::new(), - // memory_blocks: HashMap::default(), - // internal_memory_blocks: HashMap::default(), - // internal_mem_block_lengths: HashMap::default(), - // max_block_id: 0, - // data_bus: DataBus::default(), - // generated_brillig_map: HashMap::default(), - // } - // } - - fn new_with_brillig_map(generated_brillig_map: &mut HashMap) -> Context { + fn new(generated_brilligs: &mut HashMap) -> Context { let mut acir_context = AcirContext::default(); let current_side_effects_enabled_var = acir_context.add_constant(FieldElement::one()); @@ -267,7 +249,7 @@ impl<'a> Context<'a> { internal_mem_block_lengths: HashMap::default(), max_block_id: 0, data_bus: DataBus::default(), - generated_brillig_map, + generated_brillig_map: generated_brilligs, } } @@ -672,15 +654,6 @@ impl<'a> Context<'a> { output_values }; - // let output_values = self.acir_context.brillig( - // self.current_side_effects_enabled_var, - // code, - // inputs, - // outputs, - // true, - // false, - // )?; - // Compiler sanity check assert_eq!(result_ids.len(), output_values.len(), "ICE: The number of Brillig output values should match the result ids in SSA"); diff --git a/noir/noir-repo/cspell.json b/noir/noir-repo/cspell.json index 16de9757fb88..a75b49703dd6 100644 --- a/noir/noir-repo/cspell.json +++ b/noir/noir-repo/cspell.json @@ -27,6 +27,7 @@ "boilerplates", "bridgekeeper", "brillig", + "brilligs", "bytecount", "cachix", "callsite", diff --git a/noir/noir-repo/tooling/debugger/src/context.rs b/noir/noir-repo/tooling/debugger/src/context.rs index 1b054a27ff0c..5639407df54f 100644 --- a/noir/noir-repo/tooling/debugger/src/context.rs +++ b/noir/noir-repo/tooling/debugger/src/context.rs @@ -47,7 +47,7 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { ) -> Self { let source_to_opcodes = build_source_to_opcode_debug_mappings(debug_artifact); Self { - // TODO: need to handle brillig in the debugger + // TODO: need to handle brillig pointer in the debugger acvm: ACVM::new( blackbox_solver, &circuit.opcodes, From 3885f4703ab9817834d0d4b7e023e93ceb46ef15 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 12 Apr 2024 16:13:41 +0000 Subject: [PATCH 09/47] cargo fmt --- noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs | 4 ++-- noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs | 1 - noir/noir-repo/acvm-repo/acvm/tests/solver.rs | 15 ++++++++++----- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs index 4fc12cdeef97..715c3520cec7 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs @@ -78,7 +78,7 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { memory, &brillig.inputs, &brillig.bytecode, - bb_solver + bb_solver, )?; Ok(Self { vm, acir_index }) } @@ -98,7 +98,7 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { memory, &brillig_pointer.inputs, brillig_bytecode, - bb_solver + bb_solver, )?; Ok(Self { vm, acir_index }) } diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index fdec8bb14126..b62a8c1dc586 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -563,7 +563,6 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { self.acir_call_counter += 1; Ok(None) } - } // Returns the concrete value for a particular witness diff --git a/noir/noir-repo/acvm-repo/acvm/tests/solver.rs b/noir/noir-repo/acvm-repo/acvm/tests/solver.rs index be24b59dc303..446e3e9823fe 100644 --- a/noir/noir-repo/acvm-repo/acvm/tests/solver.rs +++ b/noir/noir-repo/acvm-repo/acvm/tests/solver.rs @@ -105,7 +105,8 @@ fn inversion_brillig_oracle_equivalence() { ]) .into(); let unconstrained_functions = vec![]; - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments, &unconstrained_functions); + let mut acvm = + ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments, &unconstrained_functions); // use the partial witness generation solver with our acir program let solver_status = acvm.solve(); @@ -242,7 +243,8 @@ fn double_inversion_brillig_oracle() { ]) .into(); let unconstrained_functions = vec![]; - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments, &unconstrained_functions); + let mut acvm = + ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments, &unconstrained_functions); // use the partial witness generation solver with our acir program let solver_status = acvm.solve(); @@ -371,7 +373,8 @@ fn oracle_dependent_execution() { let witness_assignments = BTreeMap::from([(w_x, FieldElement::from(2u128)), (w_y, FieldElement::from(2u128))]).into(); let unconstrained_functions = vec![]; - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments, &unconstrained_functions); + let mut acvm = + ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments, &unconstrained_functions); // use the partial witness generation solver with our acir program let solver_status = acvm.solve(); @@ -475,7 +478,8 @@ fn brillig_oracle_predicate() { ]) .into(); let unconstrained_functions = vec![]; - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments, &unconstrained_functions); + let mut acvm = + ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments, &unconstrained_functions); let solver_status = acvm.solve(); assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); @@ -637,7 +641,8 @@ fn memory_operations() { let opcodes = vec![init, read_op, expression]; let unconstrained_functions = vec![]; - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, initial_witness, &unconstrained_functions); + let mut acvm = + ACVM::new(&StubbedBlackBoxSolver, &opcodes, initial_witness, &unconstrained_functions); let solver_status = acvm.solve(); assert_eq!(solver_status, ACVMStatus::Solved); let witness_map = acvm.finalize(); From 202534b1e0c908406f76bd013170537ba6e5ba38 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Fri, 12 Apr 2024 17:29:06 +0100 Subject: [PATCH 10/47] Apply suggestions from code review --- noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs | 4 ++-- .../noir-repo/tooling/backend_interface/src/smart_contract.rs | 2 +- noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs index 42f21d29bc72..27d8a392c818 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs @@ -387,7 +387,7 @@ mod tests { assert_messages: Default::default(), recursive: false, }; - let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; + let program = Program { functions: vec![circuit], unconstrained_functions: Vec::new() }; fn read_write(program: Program) -> (Program, Program) { let bytes = Program::serialize_program(&program); @@ -420,7 +420,7 @@ mod tests { assert_messages: Default::default(), recursive: false, }; - let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; + let program = Program { functions: vec![circuit], unconstrained_functions: Vec::new() }; let json = serde_json::to_string_pretty(&program).unwrap(); diff --git a/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs b/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs index cd665c60fb14..e2e5471a6717 100644 --- a/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs +++ b/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs @@ -59,7 +59,7 @@ mod tests { assert_messages: Default::default(), recursive: false, }; - let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; + let program = Program { functions: vec![circuit], unconstrained_functions: Vec::new() }; let contract = get_mock_backend()?.eth_contract(&program)?; diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs index 19470f9292cb..28f6fc8e22c5 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs @@ -292,7 +292,7 @@ fn count_opcodes_and_gates_in_program( // Unconstrained functions do not matter to a backend circuit count so we pass nothing here circuit_size: backend.get_exact_circuit_size(&Program { functions: vec![function], - unconstrained_functions: vec![], + unconstrained_functions: Vec::new() })?, }) }) From 3d79f62642eea5207de82d065c8c4f2104dcf147 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 12 Apr 2024 16:55:17 +0000 Subject: [PATCH 11/47] use Vec inside of map for generated brilligs --- .../acvm-repo/acvm/src/pwg/brillig.rs | 1 + noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs | 2 +- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 3 ++- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 27 +++++++++---------- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs index 715c3520cec7..f0597f815c68 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs @@ -256,6 +256,7 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { } } } + assert!( current_ret_data_idx == return_data_offset + return_data_size, "Brillig VM did not write the expected number of return values" diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index b62a8c1dc586..c42bf6b8d2da 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; use acir::{ brillig::ForeignCallResult, circuit::{ - brillig::{Brillig, BrilligBytecode}, + brillig::BrilligBytecode, opcodes::BlockId, Opcode, OpcodeLocation, }, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 736e5418efad..d42a1bf306ac 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1553,6 +1553,7 @@ impl AcirContext { Ok(outputs_var) } + #[allow(clippy::too_many_arguments)] pub(crate) fn brillig_pointer( &mut self, predicate: AcirVar, @@ -1612,7 +1613,7 @@ impl AcirContext { self.acir_ir.brillig_pointer( Some(predicate), - &generated_brillig, + generated_brillig, b_inputs, b_outputs, brillig_function_index, 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 d0f684b4c061..2566ddaa18a3 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 @@ -94,7 +94,7 @@ struct Context<'a> { data_bus: DataBus, // TODO: could make this a Vec as the IDs have already made to be consecutive indices - generated_brillig_map: &'a mut HashMap, + generated_brilligs: &'a mut Vec, } #[derive(Clone)] @@ -188,10 +188,10 @@ impl Ssa { ) -> Result<(Vec, Vec), RuntimeError> { let mut acirs = Vec::new(); // TODO: can we parallelise this? - let mut generated_brillig_map = HashMap::default(); + let mut generated_brilligs = Vec::new(); for function in self.functions.values() { // let context = Context::new(); - let context = Context::new(&mut generated_brillig_map); + let context = Context::new(&mut generated_brilligs); if let Some(mut generated_acir) = context.convert_ssa_function(&self, function, brillig)? { @@ -201,9 +201,9 @@ impl Ssa { } // TODO: can just store the Brillig bytecode as we utilize the locations when setting acir locations - let brilligs = generated_brillig_map - .iter() - .map(|(_, brillig)| BrilligBytecode { bytecode: brillig.byte_code.clone() }) + let brilligs = generated_brilligs + .into_iter() + .map(|brillig| BrilligBytecode { bytecode: brillig.byte_code.clone() }) .collect::>(); // TODO: check whether doing this for a single circuit's return witnesses is correct. @@ -235,7 +235,7 @@ impl Ssa { } impl<'a> Context<'a> { - fn new(generated_brilligs: &mut HashMap) -> Context { + fn new(generated_brilligs: &mut Vec) -> Context { let mut acir_context = AcirContext::default(); let current_side_effects_enabled_var = acir_context.add_constant(FieldElement::one()); @@ -249,7 +249,7 @@ impl<'a> Context<'a> { internal_mem_block_lengths: HashMap::default(), max_block_id: 0, data_bus: DataBus::default(), - generated_brillig_map: generated_brilligs, + generated_brilligs, } } @@ -615,7 +615,6 @@ impl<'a> Context<'a> { .id_to_index .get(id) .expect("ICE: should have an associated final index"); - dbg!(brillig_program_id); let inputs = vecmap(arguments, |arg| self.convert_value(*arg, dfg)); @@ -623,10 +622,8 @@ impl<'a> Context<'a> { dfg.type_of_value(*result_id).into() }); - let output_values = if let Some(code) = - self.generated_brillig_map.get(brillig_program_id) - { - dbg!("got previous generated brillig"); + let output_values = if *brillig_program_id < self.generated_brilligs.len() as u32 { + let code = &self.generated_brilligs[*brillig_program_id as usize]; self.acir_context.brillig_pointer( self.current_side_effects_enabled_var, code, @@ -639,7 +636,7 @@ impl<'a> Context<'a> { } else { let arguments = self.gen_brillig_parameters(arguments, dfg); let code = self.gen_brillig_for(func, arguments, brillig)?; - // dbg!(code.byte_code.clone()); + let output_values = self.acir_context.brillig_pointer( self.current_side_effects_enabled_var, &code, @@ -650,7 +647,7 @@ impl<'a> Context<'a> { *brillig_program_id, )?; - self.generated_brillig_map.insert(*brillig_program_id, code); + self.generated_brilligs.push(code); output_values }; From 0b5ae021308408954f59ec57d151d680463e4045 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 12 Apr 2024 16:56:53 +0000 Subject: [PATCH 12/47] cargo fmt --- noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs | 2 +- noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs | 6 +----- .../compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs | 7 +++++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs index f0597f815c68..bc427af4937a 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs @@ -256,7 +256,7 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { } } } - + assert!( current_ret_data_idx == return_data_offset + return_data_size, "Brillig VM did not write the expected number of return values" diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index c42bf6b8d2da..f929a7d4c0fc 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -4,11 +4,7 @@ use std::collections::HashMap; use acir::{ brillig::ForeignCallResult, - circuit::{ - brillig::BrilligBytecode, - opcodes::BlockId, - Opcode, OpcodeLocation, - }, + circuit::{brillig::BrilligBytecode, opcodes::BlockId, Opcode, OpcodeLocation}, native_types::{Expression, Witness, WitnessMap}, BlackBoxFunc, FieldElement, }; 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 2566ddaa18a3..3013ffc54701 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 @@ -622,8 +622,11 @@ impl<'a> Context<'a> { dfg.type_of_value(*result_id).into() }); - let output_values = if *brillig_program_id < self.generated_brilligs.len() as u32 { - let code = &self.generated_brilligs[*brillig_program_id as usize]; + let output_values = if *brillig_program_id + < self.generated_brilligs.len() as u32 + { + let code = + &self.generated_brilligs[*brillig_program_id as usize]; self.acir_context.brillig_pointer( self.current_side_effects_enabled_var, code, From 157081843777b64b0da538bdc29ebd124fa38ff9 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 12 Apr 2024 17:29:43 +0000 Subject: [PATCH 13/47] fix to use generated index when setting brillig pointer --- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) 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 3013ffc54701..9c2cbbba13b1 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 @@ -1,7 +1,7 @@ //! This file holds the pass to convert from Noir's SSA IR to ACIR. mod acir_ir; -use std::collections::HashSet; +use std::collections::{BTreeMap, HashSet}; use std::fmt::Debug; use self::acir_ir::acir_variable::{AcirContext, AcirType, AcirVar}; @@ -94,7 +94,12 @@ struct Context<'a> { data_bus: DataBus, // TODO: could make this a Vec as the IDs have already made to be consecutive indices - generated_brilligs: &'a mut Vec, + generated_brilligs: &'a mut BTreeMap, + + /// Represents the index of a function from SSA to its final index + /// We need this in case there are functions which have been specified in SSA + /// but ultimately were not used during ACIR gen + brillig_index_to_gen_index: BTreeMap, } #[derive(Clone)] @@ -188,10 +193,10 @@ impl Ssa { ) -> Result<(Vec, Vec), RuntimeError> { let mut acirs = Vec::new(); // TODO: can we parallelise this? - let mut generated_brilligs = Vec::new(); + let mut generated_brillig_map = BTreeMap::default(); for function in self.functions.values() { // let context = Context::new(); - let context = Context::new(&mut generated_brilligs); + let context = Context::new(&mut generated_brillig_map); if let Some(mut generated_acir) = context.convert_ssa_function(&self, function, brillig)? { @@ -201,8 +206,8 @@ impl Ssa { } // TODO: can just store the Brillig bytecode as we utilize the locations when setting acir locations - let brilligs = generated_brilligs - .into_iter() + let brilligs = generated_brillig_map + .values() .map(|brillig| BrilligBytecode { bytecode: brillig.byte_code.clone() }) .collect::>(); @@ -235,7 +240,7 @@ impl Ssa { } impl<'a> Context<'a> { - fn new(generated_brilligs: &mut Vec) -> Context { + fn new(generated_brilligs: &mut BTreeMap) -> Context { let mut acir_context = AcirContext::default(); let current_side_effects_enabled_var = acir_context.add_constant(FieldElement::one()); @@ -250,6 +255,7 @@ impl<'a> Context<'a> { max_block_id: 0, data_bus: DataBus::default(), generated_brilligs, + brillig_index_to_gen_index: BTreeMap::default(), } } @@ -622,11 +628,8 @@ impl<'a> Context<'a> { dfg.type_of_value(*result_id).into() }); - let output_values = if *brillig_program_id - < self.generated_brilligs.len() as u32 - { - let code = - &self.generated_brilligs[*brillig_program_id as usize]; + let output_values = if let Some(gen_index) = self.brillig_index_to_gen_index.get(brillig_program_id) { + let code = self.generated_brilligs.get(gen_index).expect("should have gen brillig"); self.acir_context.brillig_pointer( self.current_side_effects_enabled_var, code, @@ -634,12 +637,13 @@ impl<'a> Context<'a> { outputs, true, false, - *brillig_program_id, + *gen_index, )? } else { let arguments = self.gen_brillig_parameters(arguments, dfg); let code = self.gen_brillig_for(func, arguments, brillig)?; + let final_generated_index = self.generated_brilligs.len() as u32; let output_values = self.acir_context.brillig_pointer( self.current_side_effects_enabled_var, &code, @@ -647,10 +651,11 @@ impl<'a> Context<'a> { outputs, true, false, - *brillig_program_id, + final_generated_index, )?; - self.generated_brilligs.push(code); + self.brillig_index_to_gen_index.insert(*brillig_program_id, final_generated_index); + self.generated_brilligs.insert(final_generated_index, code); output_values }; From 0beb7fb2a6cde2f10fca9100ffa2fbb90cea1495 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 12 Apr 2024 17:31:30 +0000 Subject: [PATCH 14/47] cargo mft --- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) 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 9c2cbbba13b1..fc4b98c7f538 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 @@ -628,8 +628,13 @@ impl<'a> Context<'a> { dfg.type_of_value(*result_id).into() }); - let output_values = if let Some(gen_index) = self.brillig_index_to_gen_index.get(brillig_program_id) { - let code = self.generated_brilligs.get(gen_index).expect("should have gen brillig"); + let output_values = if let Some(gen_index) = + self.brillig_index_to_gen_index.get(brillig_program_id) + { + let code = self + .generated_brilligs + .get(gen_index) + .expect("should have gen brillig"); self.acir_context.brillig_pointer( self.current_side_effects_enabled_var, code, @@ -643,7 +648,8 @@ impl<'a> Context<'a> { let arguments = self.gen_brillig_parameters(arguments, dfg); let code = self.gen_brillig_for(func, arguments, brillig)?; - let final_generated_index = self.generated_brilligs.len() as u32; + let final_generated_index = + self.generated_brilligs.len() as u32; let output_values = self.acir_context.brillig_pointer( self.current_side_effects_enabled_var, &code, @@ -654,7 +660,8 @@ impl<'a> Context<'a> { final_generated_index, )?; - self.brillig_index_to_gen_index.insert(*brillig_program_id, final_generated_index); + self.brillig_index_to_gen_index + .insert(*brillig_program_id, final_generated_index); self.generated_brilligs.insert(final_generated_index, code); output_values }; From 7f7ddf38dd6d98616b9169a6151e14acaf078c56 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 12 Apr 2024 18:09:08 +0000 Subject: [PATCH 15/47] update instance deployer address --- yarn-project/circuits.js/src/constants.gen.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 34818ffb7d8d..0687998f8779 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 = 0x1d144e236f9df5ca2e46d274585f322f16502b33a91cd24bce24c93b73dde3c5n; +export const DEPLOYER_CONTRACT_ADDRESS = 0x1674e9ab953fadc1d2140a5f9c8e36037f9b747001af69ba114df0c19d66bcb0n; 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; From db06865745a5dc4fe58a1b54ef5d398fadec82a8 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 12 Apr 2024 20:01:49 +0000 Subject: [PATCH 16/47] some improvements, store GeneratedBrilligs during SSA as a Vec --- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) 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 fc4b98c7f538..019a2e5763c1 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 @@ -93,10 +93,16 @@ struct Context<'a> { data_bus: DataBus, - // TODO: could make this a Vec as the IDs have already made to be consecutive indices - generated_brilligs: &'a mut BTreeMap, - - /// Represents the index of a function from SSA to its final index + /// Final list of Brillig functions which will be part of the final program + /// This is shared across `Context` structs as we want one list of Brillig + /// functions across all ACIR artifacts + generated_brilligs: &'a mut Vec, + + // TODO: Move this into a shared context with `generated_brilligs` + /// Maps SSA function index -> Final generated Brillig artifact index + /// Represents the index of a function from SSA to its final generated index. + /// There can be Brillig functions specified in SSA which do not act as + /// entry points in ACIR (e.g. only called by other Brillig functions) /// We need this in case there are functions which have been specified in SSA /// but ultimately were not used during ACIR gen brillig_index_to_gen_index: BTreeMap, @@ -193,10 +199,9 @@ impl Ssa { ) -> Result<(Vec, Vec), RuntimeError> { let mut acirs = Vec::new(); // TODO: can we parallelise this? - let mut generated_brillig_map = BTreeMap::default(); + let mut generated_brilligs = Vec::default(); for function in self.functions.values() { - // let context = Context::new(); - let context = Context::new(&mut generated_brillig_map); + let context = Context::new(&mut generated_brilligs); if let Some(mut generated_acir) = context.convert_ssa_function(&self, function, brillig)? { @@ -205,11 +210,8 @@ impl Ssa { } } - // TODO: can just store the Brillig bytecode as we utilize the locations when setting acir locations - let brilligs = generated_brillig_map - .values() - .map(|brillig| BrilligBytecode { bytecode: brillig.byte_code.clone() }) - .collect::>(); + let brilligs = + vecmap(generated_brilligs, |brillig| BrilligBytecode { bytecode: brillig.byte_code }); // TODO: check whether doing this for a single circuit's return witnesses is correct. // We probably need it for all foldable circuits, as any circuit being folded is essentially an entry point. However, I do not know how that @@ -240,7 +242,7 @@ impl Ssa { } impl<'a> Context<'a> { - fn new(generated_brilligs: &mut BTreeMap) -> Context { + fn new(generated_brilligs: &mut Vec) -> Context { let mut acir_context = AcirContext::default(); let current_side_effects_enabled_var = acir_context.add_constant(FieldElement::one()); @@ -631,10 +633,7 @@ impl<'a> Context<'a> { let output_values = if let Some(gen_index) = self.brillig_index_to_gen_index.get(brillig_program_id) { - let code = self - .generated_brilligs - .get(gen_index) - .expect("should have gen brillig"); + let code = &self.generated_brilligs[*gen_index as usize]; self.acir_context.brillig_pointer( self.current_side_effects_enabled_var, code, @@ -662,7 +661,7 @@ impl<'a> Context<'a> { self.brillig_index_to_gen_index .insert(*brillig_program_id, final_generated_index); - self.generated_brilligs.insert(final_generated_index, code); + self.generated_brilligs.push(code); output_values }; From dcf586dc7f13032f63f80da12952dc6cdf4f1335 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 12 Apr 2024 20:06:27 +0000 Subject: [PATCH 17/47] make both brillig func info a mutable reference on an AcirContext --- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) 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 019a2e5763c1..b298c958eb88 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 @@ -98,14 +98,13 @@ struct Context<'a> { /// functions across all ACIR artifacts generated_brilligs: &'a mut Vec, - // TODO: Move this into a shared context with `generated_brilligs` /// Maps SSA function index -> Final generated Brillig artifact index /// Represents the index of a function from SSA to its final generated index. /// There can be Brillig functions specified in SSA which do not act as /// entry points in ACIR (e.g. only called by other Brillig functions) /// We need this in case there are functions which have been specified in SSA /// but ultimately were not used during ACIR gen - brillig_index_to_gen_index: BTreeMap, + brillig_index_to_gen_index: &'a mut BTreeMap, } #[derive(Clone)] @@ -200,8 +199,9 @@ impl Ssa { let mut acirs = Vec::new(); // TODO: can we parallelise this? let mut generated_brilligs = Vec::default(); + let mut brillig_index_to_gen_index = BTreeMap::default(); for function in self.functions.values() { - let context = Context::new(&mut generated_brilligs); + let context = Context::new(&mut generated_brilligs, &mut brillig_index_to_gen_index); if let Some(mut generated_acir) = context.convert_ssa_function(&self, function, brillig)? { @@ -242,7 +242,10 @@ impl Ssa { } impl<'a> Context<'a> { - fn new(generated_brilligs: &mut Vec) -> Context { + fn new( + generated_brilligs: &'a mut Vec, + brillig_index_to_gen_index: &'a mut BTreeMap, + ) -> Context<'a> { let mut acir_context = AcirContext::default(); let current_side_effects_enabled_var = acir_context.add_constant(FieldElement::one()); @@ -257,7 +260,7 @@ impl<'a> Context<'a> { max_block_id: 0, data_bus: DataBus::default(), generated_brilligs, - brillig_index_to_gen_index: BTreeMap::default(), + brillig_index_to_gen_index, } } From 30281148e03dd4df37d0a81249594894f049bc22 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Sat, 13 Apr 2024 00:05:38 +0100 Subject: [PATCH 18/47] Update noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs --- noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs index 28f6fc8e22c5..e9609687ffb7 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs @@ -292,7 +292,7 @@ fn count_opcodes_and_gates_in_program( // Unconstrained functions do not matter to a backend circuit count so we pass nothing here circuit_size: backend.get_exact_circuit_size(&Program { functions: vec![function], - unconstrained_functions: Vec::new() + unconstrained_functions: Vec::new(), })?, }) }) From 32536f85c8ae30af31aa4ab9746885c7f06115f2 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 15 Apr 2024 14:47:13 +0000 Subject: [PATCH 19/47] change serde to BrilligCall and no inner struct --- .../dsl/acir_format/serde/acir.hpp | 201 +++++++----------- .../noir-repo/acvm-repo/acir/codegen/acir.cpp | 168 +++++---------- .../acvm-repo/acir/src/circuit/brillig.rs | 10 - .../acvm-repo/acir/src/circuit/opcodes.rs | 29 ++- noir/noir-repo/acvm-repo/acir/src/lib.rs | 8 +- .../acvm/src/compiler/transformers/mod.rs | 5 +- noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs | 2 +- 7 files changed, 161 insertions(+), 262 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp index 490c91d87172..9910b7a68542 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp @@ -1041,17 +1041,6 @@ struct Brillig { static Brillig bincodeDeserialize(std::vector); }; -struct BrilligPointer { - std::vector inputs; - std::vector outputs; - uint32_t bytecode_index; - std::optional predicate; - - friend bool operator==(const BrilligPointer&, const BrilligPointer&); - std::vector bincodeSerialize() const; - static BrilligPointer bincodeDeserialize(std::vector); -}; - struct Directive { struct ToLeRadix { @@ -1115,14 +1104,6 @@ struct Opcode { static Brillig bincodeDeserialize(std::vector); }; - struct BrilligPointer { - Program::BrilligPointer value; - - friend bool operator==(const BrilligPointer&, const BrilligPointer&); - std::vector bincodeSerialize() const; - static BrilligPointer bincodeDeserialize(std::vector); - }; - struct MemoryOp { Program::BlockId block_id; Program::MemOp op; @@ -1142,6 +1123,17 @@ struct Opcode { static MemoryInit bincodeDeserialize(std::vector); }; + struct BrilligCall { + std::vector inputs; + std::vector outputs; + uint32_t bytecode_index; + std::optional predicate; + + friend bool operator==(const BrilligCall&, const BrilligCall&); + std::vector bincodeSerialize() const; + static BrilligCall bincodeDeserialize(std::vector); + }; + struct Call { uint32_t id; std::vector inputs; @@ -1153,7 +1145,7 @@ struct Opcode { static Call bincodeDeserialize(std::vector); }; - std::variant value; + std::variant value; friend bool operator==(const Opcode&, const Opcode&); std::vector bincodeSerialize() const; @@ -6302,70 +6294,6 @@ Program::BrilligOutputs::Array serde::Deserializable BrilligPointer::bincodeSerialize() const -{ - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} - -inline BrilligPointer BrilligPointer::bincodeDeserialize(std::vector input) -{ - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; -} - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize(const Program::BrilligPointer& obj, Serializer& serializer) -{ - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.outputs, serializer); - serde::Serializable::serialize(obj.bytecode_index, serializer); - serde::Serializable::serialize(obj.predicate, serializer); - serializer.decrease_container_depth(); -} - -template <> -template -Program::BrilligPointer serde::Deserializable::deserialize(Deserializer& deserializer) -{ - deserializer.increase_container_depth(); - Program::BrilligPointer obj; - obj.inputs = serde::Deserializable::deserialize(deserializer); - obj.outputs = serde::Deserializable::deserialize(deserializer); - obj.bytecode_index = serde::Deserializable::deserialize(deserializer); - obj.predicate = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; -} - -namespace Program { - inline bool operator==(const Circuit& lhs, const Circuit& rhs) { if (!(lhs.current_witness_index == rhs.current_witness_index)) { @@ -7452,25 +7380,31 @@ Program::Opcode::Brillig serde::Deserializable::deseri namespace Program { -inline bool operator==(const Opcode::BrilligPointer& lhs, const Opcode::BrilligPointer& rhs) +inline bool operator==(const Opcode::MemoryOp& lhs, const Opcode::MemoryOp& rhs) { - if (!(lhs.value == rhs.value)) { + if (!(lhs.block_id == rhs.block_id)) { + return false; + } + if (!(lhs.op == rhs.op)) { + return false; + } + if (!(lhs.predicate == rhs.predicate)) { return false; } return true; } -inline std::vector Opcode::BrilligPointer::bincodeSerialize() const +inline std::vector Opcode::MemoryOp::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } -inline Opcode::BrilligPointer Opcode::BrilligPointer::bincodeDeserialize(std::vector input) +inline Opcode::MemoryOp Opcode::MemoryOp::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw_or_abort("Some input bytes were not read"); } @@ -7481,49 +7415,49 @@ inline Opcode::BrilligPointer Opcode::BrilligPointer::bincodeDeserialize(std::ve template <> template -void serde::Serializable::serialize(const Program::Opcode::BrilligPointer& obj, - Serializer& serializer) +void serde::Serializable::serialize(const Program::Opcode::MemoryOp& obj, + Serializer& serializer) { - serde::Serializable::serialize(obj.value, serializer); + serde::Serializable::serialize(obj.block_id, serializer); + serde::Serializable::serialize(obj.op, serializer); + serde::Serializable::serialize(obj.predicate, serializer); } template <> template -Program::Opcode::BrilligPointer serde::Deserializable::deserialize( - Deserializer& deserializer) +Program::Opcode::MemoryOp serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::Opcode::BrilligPointer obj; - obj.value = serde::Deserializable::deserialize(deserializer); + Program::Opcode::MemoryOp obj; + obj.block_id = serde::Deserializable::deserialize(deserializer); + obj.op = serde::Deserializable::deserialize(deserializer); + obj.predicate = serde::Deserializable::deserialize(deserializer); return obj; } namespace Program { -inline bool operator==(const Opcode::MemoryOp& lhs, const Opcode::MemoryOp& rhs) +inline bool operator==(const Opcode::MemoryInit& lhs, const Opcode::MemoryInit& rhs) { if (!(lhs.block_id == rhs.block_id)) { return false; } - if (!(lhs.op == rhs.op)) { - return false; - } - if (!(lhs.predicate == rhs.predicate)) { + if (!(lhs.init == rhs.init)) { return false; } return true; } -inline std::vector Opcode::MemoryOp::bincodeSerialize() const +inline std::vector Opcode::MemoryInit::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } -inline Opcode::MemoryOp Opcode::MemoryOp::bincodeDeserialize(std::vector input) +inline Opcode::MemoryInit Opcode::MemoryInit::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw_or_abort("Some input bytes were not read"); } @@ -7534,49 +7468,53 @@ inline Opcode::MemoryOp Opcode::MemoryOp::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::Opcode::MemoryOp& obj, - Serializer& serializer) +void serde::Serializable::serialize(const Program::Opcode::MemoryInit& obj, + Serializer& serializer) { serde::Serializable::serialize(obj.block_id, serializer); - serde::Serializable::serialize(obj.op, serializer); - serde::Serializable::serialize(obj.predicate, serializer); + serde::Serializable::serialize(obj.init, serializer); } template <> template -Program::Opcode::MemoryOp serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Opcode::MemoryInit serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::Opcode::MemoryOp obj; + Program::Opcode::MemoryInit obj; obj.block_id = serde::Deserializable::deserialize(deserializer); - obj.op = serde::Deserializable::deserialize(deserializer); - obj.predicate = serde::Deserializable::deserialize(deserializer); + obj.init = serde::Deserializable::deserialize(deserializer); return obj; } namespace Program { -inline bool operator==(const Opcode::MemoryInit& lhs, const Opcode::MemoryInit& rhs) +inline bool operator==(const Opcode::BrilligCall& lhs, const Opcode::BrilligCall& rhs) { - if (!(lhs.block_id == rhs.block_id)) { + if (!(lhs.inputs == rhs.inputs)) { return false; } - if (!(lhs.init == rhs.init)) { + if (!(lhs.outputs == rhs.outputs)) { + return false; + } + if (!(lhs.bytecode_index == rhs.bytecode_index)) { + return false; + } + if (!(lhs.predicate == rhs.predicate)) { return false; } return true; } -inline std::vector Opcode::MemoryInit::bincodeSerialize() const +inline std::vector Opcode::BrilligCall::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } -inline Opcode::MemoryInit Opcode::MemoryInit::bincodeDeserialize(std::vector input) +inline Opcode::BrilligCall Opcode::BrilligCall::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw_or_abort("Some input bytes were not read"); } @@ -7587,20 +7525,25 @@ inline Opcode::MemoryInit Opcode::MemoryInit::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::Opcode::MemoryInit& obj, - Serializer& serializer) +void serde::Serializable::serialize(const Program::Opcode::BrilligCall& obj, + Serializer& serializer) { - serde::Serializable::serialize(obj.block_id, serializer); - serde::Serializable::serialize(obj.init, serializer); + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.outputs, serializer); + serde::Serializable::serialize(obj.bytecode_index, serializer); + serde::Serializable::serialize(obj.predicate, serializer); } template <> template -Program::Opcode::MemoryInit serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Opcode::BrilligCall serde::Deserializable::deserialize( + Deserializer& deserializer) { - Program::Opcode::MemoryInit obj; - obj.block_id = serde::Deserializable::deserialize(deserializer); - obj.init = serde::Deserializable::deserialize(deserializer); + Program::Opcode::BrilligCall obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + obj.bytecode_index = serde::Deserializable::deserialize(deserializer); + obj.predicate = serde::Deserializable::deserialize(deserializer); return obj; } diff --git a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp index ce899df34d07..634faaac8033 100644 --- a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp +++ b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp @@ -979,17 +979,6 @@ namespace Program { static Brillig bincodeDeserialize(std::vector); }; - struct BrilligPointer { - std::vector inputs; - std::vector outputs; - uint32_t bytecode_index; - std::optional predicate; - - friend bool operator==(const BrilligPointer&, const BrilligPointer&); - std::vector bincodeSerialize() const; - static BrilligPointer bincodeDeserialize(std::vector); - }; - struct Directive { struct ToLeRadix { @@ -1053,14 +1042,6 @@ namespace Program { static Brillig bincodeDeserialize(std::vector); }; - struct BrilligPointer { - Program::BrilligPointer value; - - friend bool operator==(const BrilligPointer&, const BrilligPointer&); - std::vector bincodeSerialize() const; - static BrilligPointer bincodeDeserialize(std::vector); - }; - struct MemoryOp { Program::BlockId block_id; Program::MemOp op; @@ -1080,6 +1061,17 @@ namespace Program { static MemoryInit bincodeDeserialize(std::vector); }; + struct BrilligCall { + std::vector inputs; + std::vector outputs; + uint32_t bytecode_index; + std::optional predicate; + + friend bool operator==(const BrilligCall&, const BrilligCall&); + std::vector bincodeSerialize() const; + static BrilligCall bincodeDeserialize(std::vector); + }; + struct Call { uint32_t id; std::vector inputs; @@ -1091,7 +1083,7 @@ namespace Program { static Call bincodeDeserialize(std::vector); }; - std::variant value; + std::variant value; friend bool operator==(const Opcode&, const Opcode&); std::vector bincodeSerialize() const; @@ -5213,57 +5205,6 @@ Program::BrilligOutputs::Array serde::Deserializable BrilligPointer::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BrilligPointer BrilligPointer::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize(const Program::BrilligPointer &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.outputs, serializer); - serde::Serializable::serialize(obj.bytecode_index, serializer); - serde::Serializable::serialize(obj.predicate, serializer); - serializer.decrease_container_depth(); -} - -template <> -template -Program::BrilligPointer serde::Deserializable::deserialize(Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::BrilligPointer obj; - obj.inputs = serde::Deserializable::deserialize(deserializer); - obj.outputs = serde::Deserializable::deserialize(deserializer); - obj.bytecode_index = serde::Deserializable::deserialize(deserializer); - obj.predicate = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; -} - namespace Program { inline bool operator==(const Circuit &lhs, const Circuit &rhs) { @@ -6154,44 +6095,6 @@ Program::Opcode::Brillig serde::Deserializable::deseri return obj; } -namespace Program { - - inline bool operator==(const Opcode::BrilligPointer &lhs, const Opcode::BrilligPointer &rhs) { - if (!(lhs.value == rhs.value)) { return false; } - return true; - } - - inline std::vector Opcode::BrilligPointer::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline Opcode::BrilligPointer Opcode::BrilligPointer::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize(const Program::Opcode::BrilligPointer &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); -} - -template <> -template -Program::Opcode::BrilligPointer serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::Opcode::BrilligPointer obj; - obj.value = serde::Deserializable::deserialize(deserializer); - return obj; -} - namespace Program { inline bool operator==(const Opcode::MemoryOp &lhs, const Opcode::MemoryOp &rhs) { @@ -6277,6 +6180,53 @@ Program::Opcode::MemoryInit serde::Deserializable:: return obj; } +namespace Program { + + inline bool operator==(const Opcode::BrilligCall &lhs, const Opcode::BrilligCall &rhs) { + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + if (!(lhs.bytecode_index == rhs.bytecode_index)) { return false; } + if (!(lhs.predicate == rhs.predicate)) { return false; } + return true; + } + + inline std::vector Opcode::BrilligCall::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline Opcode::BrilligCall Opcode::BrilligCall::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::Opcode::BrilligCall &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.outputs, serializer); + serde::Serializable::serialize(obj.bytecode_index, serializer); + serde::Serializable::serialize(obj.predicate, serializer); +} + +template <> +template +Program::Opcode::BrilligCall serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::BrilligCall obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + obj.bytecode_index = serde::Deserializable::deserialize(deserializer); + obj.predicate = serde::Deserializable::deserialize(deserializer); + return obj; +} + namespace Program { inline bool operator==(const Opcode::Call &lhs, const Opcode::Call &rhs) { diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/brillig.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/brillig.rs index 146d24ae6ccb..e75d335d52b6 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/brillig.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/brillig.rs @@ -30,16 +30,6 @@ pub struct Brillig { pub predicate: Option, } -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct BrilligPointer { - pub inputs: Vec, - pub outputs: Vec, - // A pointer to the index of the Brillig VM bytecode to be executed by the ACVM - pub bytecode_index: u32, - /// Predicate of the Brillig execution - indicates if it should be skipped - pub predicate: Option, -} - /// This is purely a wrapper struct around a list of Brillig opcode's which represents /// a full Brillig function to be executed by the Brillig VM. /// This is stored separately on a program and accessed through a [BrilligPointer]. diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs index a360aaa61230..893d6aa44c2a 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs @@ -1,5 +1,5 @@ use super::{ - brillig::{Brillig, BrilligPointer}, + brillig::{Brillig, BrilligInputs, BrilligOutputs}, directives::Directive, }; use crate::native_types::{Expression, Witness}; @@ -21,7 +21,6 @@ pub enum Opcode { BlackBoxFuncCall(BlackBoxFuncCall), Directive(Directive), Brillig(Brillig), - BrilligPointer(BrilligPointer), /// Atomic operation on a block of memory MemoryOp { block_id: BlockId, @@ -33,6 +32,17 @@ pub enum Opcode { block_id: BlockId, init: Vec, }, + /// Calls to unconstrained functions + BrilligCall { + /// Inputs to the function call + inputs: Vec, + /// Outputs to the function call + outputs: Vec, + /// A pointer to the index of the Brillig VM bytecode to be executed. + bytecode_index: u32, + /// Predicate of the Brillig execution - indicates if it should be skipped + predicate: Option, + }, /// Calls to functions represented as a separate circuit. A call opcode allows us /// to build a call stack when executing the outer-most circuit. Call { @@ -83,11 +93,6 @@ impl std::fmt::Display for Opcode { writeln!(f, "outputs: {:?}", brillig.outputs)?; writeln!(f, "{:?}", brillig.bytecode) } - Opcode::BrilligPointer(brillig) => { - write!(f, "BRILLIG {:?}: ", brillig.bytecode_index)?; - writeln!(f, "inputs: {:?}", brillig.inputs)?; - writeln!(f, "outputs: {:?}", brillig.outputs) - } Opcode::MemoryOp { block_id, op, predicate } => { write!(f, "MEM ")?; if let Some(pred) = predicate { @@ -108,6 +113,16 @@ impl std::fmt::Display for Opcode { write!(f, "INIT ")?; write!(f, "(id: {}, len: {}) ", block_id.0, init.len()) } + // We keep the display for a BrilligCall and circuit Call separate as they + // are distinct in their functionality and we should maintain this separation for debugging. + Opcode::BrilligCall { inputs, outputs, bytecode_index, predicate } => { + write!(f, "BRILLIG CALL func {}: ", bytecode_index)?; + if let Some(pred) = predicate { + writeln!(f, "PREDICATE = {pred}")?; + } + write!(f, "inputs: {:?}, ", inputs)?; + write!(f, "outputs: {:?}", outputs) + } Opcode::Call { id, inputs, outputs, predicate } => { write!(f, "CALL func {}: ", id)?; if let Some(pred) = predicate { diff --git a/noir/noir-repo/acvm-repo/acir/src/lib.rs b/noir/noir-repo/acvm-repo/acir/src/lib.rs index d14159f34a16..29e588744781 100644 --- a/noir/noir-repo/acvm-repo/acir/src/lib.rs +++ b/noir/noir-repo/acvm-repo/acir/src/lib.rs @@ -85,10 +85,10 @@ mod reflection { generator.output(&mut source, ®istry).unwrap(); // Comment this out to write updated C++ code to file. - if let Some(old_hash) = old_hash { - let new_hash = fxhash::hash64(&source); - assert_eq!(new_hash, old_hash, "Serialization format has changed"); - } + // if let Some(old_hash) = old_hash { + // let new_hash = fxhash::hash64(&source); + // assert_eq!(new_hash, old_hash, "Serialization format has changed"); + // } write_to_file(&source, &path); } diff --git a/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs index 12f7a8b0174c..d13fac1672a3 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -142,8 +142,8 @@ pub(super) fn transform_internal( new_acir_opcode_positions.push(acir_opcode_positions[index]); transformed_opcodes.push(opcode); } - Opcode::BrilligPointer(ref brillig) => { - for output in &brillig.outputs { + Opcode::BrilligCall { ref outputs, .. } => { + for output in outputs { match output { BrilligOutputs::Simple(w) => transformer.mark_solvable(*w), BrilligOutputs::Array(v) => { @@ -153,6 +153,7 @@ pub(super) fn transform_internal( } } } + new_acir_opcode_positions.push(acir_opcode_positions[index]); transformed_opcodes.push(opcode); } diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index b99453ace6a6..fd00b16cb355 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -324,7 +324,7 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { Ok(Some(foreign_call)) => return self.wait_for_foreign_call(foreign_call), res => res.map(|_| ()), }, - Opcode::BrilligPointer(_) => { + Opcode::BrilligCall { .. } => { todo!("implement brillig pointer handling"); } Opcode::Call { .. } => match self.solve_call_opcode() { From 94d4837224226715b074a47079f4fd4dd63add39 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 15 Apr 2024 14:49:16 +0000 Subject: [PATCH 20/47] undo comment in serde test --- noir/noir-repo/acvm-repo/acir/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acir/src/lib.rs b/noir/noir-repo/acvm-repo/acir/src/lib.rs index 29e588744781..d14159f34a16 100644 --- a/noir/noir-repo/acvm-repo/acir/src/lib.rs +++ b/noir/noir-repo/acvm-repo/acir/src/lib.rs @@ -85,10 +85,10 @@ mod reflection { generator.output(&mut source, ®istry).unwrap(); // Comment this out to write updated C++ code to file. - // if let Some(old_hash) = old_hash { - // let new_hash = fxhash::hash64(&source); - // assert_eq!(new_hash, old_hash, "Serialization format has changed"); - // } + if let Some(old_hash) = old_hash { + let new_hash = fxhash::hash64(&source); + assert_eq!(new_hash, old_hash, "Serialization format has changed"); + } write_to_file(&source, &path); } From a8820cb20ea8fe8ec3ca3213b9cdeeaf0964be0a Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Mon, 15 Apr 2024 16:02:56 +0100 Subject: [PATCH 21/47] Update noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs index 893d6aa44c2a..19e802b70a0b 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs @@ -34,12 +34,13 @@ pub enum Opcode { }, /// Calls to unconstrained functions BrilligCall { + /// Id for the function being called. It is the responsibility of the executor + /// to fetch the appropriate Brillig bytecode from this id. + id: u32, /// Inputs to the function call inputs: Vec, /// Outputs to the function call outputs: Vec, - /// A pointer to the index of the Brillig VM bytecode to be executed. - bytecode_index: u32, /// Predicate of the Brillig execution - indicates if it should be skipped predicate: Option, }, From 2efd923ecc875951e07788087e1a9f4161eaf273 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 15 Apr 2024 15:16:46 +0000 Subject: [PATCH 22/47] brillig call display --- noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs index 19e802b70a0b..b0b8e286e0c2 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs @@ -116,8 +116,8 @@ impl std::fmt::Display for Opcode { } // We keep the display for a BrilligCall and circuit Call separate as they // are distinct in their functionality and we should maintain this separation for debugging. - Opcode::BrilligCall { inputs, outputs, bytecode_index, predicate } => { - write!(f, "BRILLIG CALL func {}: ", bytecode_index)?; + Opcode::BrilligCall { id, inputs, outputs, predicate } => { + write!(f, "BRILLIG CALL func {}: ", id)?; if let Some(pred) = predicate { writeln!(f, "PREDICATE = {pred}")?; } From 8ca07822e14df1a2fe20b985759b7fabc90c4ceb Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 15 Apr 2024 15:53:15 +0000 Subject: [PATCH 23/47] fix mem op serde --- .../acvm-repo/acir/tests/test_program_serialization.rs | 10 +++++----- .../acvm-repo/acvm_js/test/shared/memory_op.ts | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs index 12c5565ede96..3f392be9fe9f 100644 --- a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs +++ b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs @@ -354,11 +354,11 @@ fn memory_op_circuit() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 144, 49, 14, 0, 32, 8, 3, 65, 196, 247, 224, 15, - 252, 255, 171, 52, 177, 3, 3, 155, 48, 120, 9, 41, 44, 77, 41, 211, 69, 207, 8, 246, 1, - 109, 80, 198, 174, 20, 179, 160, 246, 198, 172, 246, 229, 100, 95, 201, 243, 178, 234, 114, - 237, 183, 114, 123, 246, 239, 226, 130, 54, 119, 251, 240, 157, 2, 54, 249, 149, 243, 126, - 35, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 81, 57, 14, 0, 32, 8, 147, 195, 255, 224, 15, 252, + 255, 171, 212, 200, 208, 129, 77, 24, 108, 66, 90, 150, 166, 20, 106, 23, 125, 143, 128, + 62, 96, 103, 114, 173, 45, 198, 116, 182, 55, 140, 106, 95, 74, 246, 149, 60, 47, 171, 46, + 215, 126, 43, 87, 179, 111, 23, 8, 202, 176, 99, 248, 240, 9, 11, 137, 33, 212, 110, 35, 3, + 0, 0, ]; assert_eq!(bytes, expected_serialization) diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts index 6fd5e6a4019d..a69ae4432591 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts @@ -1,9 +1,9 @@ // See `memory_op_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 144, 49, 14, 0, 32, 8, 3, 65, 196, 247, 224, 15, 252, 255, 171, 52, 177, 3, 3, - 155, 48, 120, 9, 41, 44, 77, 41, 211, 69, 207, 8, 246, 1, 109, 80, 198, 174, 20, 179, 160, 246, 198, 172, 246, 229, - 100, 95, 201, 243, 178, 234, 114, 237, 183, 114, 123, 246, 239, 226, 130, 54, 119, 251, 240, 157, 2, 54, 249, 149, - 243, 126, 35, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 81, 57, 14, 0, 32, 8, 147, 195, 255, 224, 15, 252, 255, 171, 212, 200, 208, + 129, 77, 24, 108, 66, 90, 150, 166, 20, 106, 23, 125, 143, 128, 62, 96, 103, 114, 173, 45, 198, 116, 182, 55, 140, + 106, 95, 74, 246, 149, 60, 47, 171, 46, 215, 126, 43, 87, 179, 111, 23, 8, 202, 176, 99, 248, 240, 9, 11, 137, 33, + 212, 110, 35, 3, 0, 0, ]); export const initialWitnessMap = new Map([ From 191b1dced35a169862b6824a798bbaada7ed3dbb Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 15 Apr 2024 21:45:54 +0000 Subject: [PATCH 24/47] working again after merge conflicts --- noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs | 11 +++-------- noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs | 10 +++++----- .../src/ssa/acir_gen/acir_ir/generated_acir.rs | 10 +++------- .../noirc_evaluator/src/ssa/ssa_gen/program.rs | 16 ++++++++++++---- .../fold_after_inlined_calls/Nargo.toml | 7 +++++++ .../fold_after_inlined_calls/Prover.toml | 1 + .../fold_after_inlined_calls/src/main.nr | 14 ++++++++++++++ 7 files changed, 45 insertions(+), 24 deletions(-) create mode 100644 noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/src/main.nr diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs index 4154c1a9fdb3..0a36a16545b9 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use acir::{ brillig::{ForeignCallParam, ForeignCallResult, Opcode as BrilligOpcode}, circuit::{ - brillig::{Brillig, BrilligInputs, BrilligOutputs, BrilligPointer}, + brillig::{Brillig, BrilligInputs, BrilligOutputs}, opcodes::BlockId, OpcodeLocation, }, @@ -93,13 +93,8 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { bb_solver: &'b B, acir_index: usize, ) -> Result { - let vm = Self::setup_brillig_vm( - initial_witness, - memory, - &brillig_pointer.inputs, - brillig_bytecode, - bb_solver, - )?; + let vm = + Self::setup_brillig_vm(initial_witness, memory, inputs, brillig_bytecode, bb_solver)?; Ok(Self { vm, acir_index }) } diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index 42e1b9f54e5b..26716b65d3b5 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -337,7 +337,7 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { Ok(Some(foreign_call)) => return self.wait_for_foreign_call(foreign_call), res => res.map(|_| ()), }, - Opcode::BrilligCall { .. }=> match self.solve_brillig_call_opcode() { + Opcode::BrilligCall { .. } => match self.solve_brillig_call_opcode() { Ok(Some(foreign_call)) => return self.wait_for_foreign_call(foreign_call), res => res.map(|_| ()), }, @@ -431,15 +431,15 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { fn solve_brillig_call_opcode( &mut self, ) -> Result, OpcodeResolutionError> { - let Opcode::BrilligCall { id, inputs, outputs, predicate } = &self.opcodes[self.instruction_pointer] + let Opcode::BrilligCall { id, inputs, outputs, predicate } = + &self.opcodes[self.instruction_pointer] else { unreachable!("Not executing a Brillig opcode"); }; let witness = &mut self.witness_map; if is_predicate_false(witness, &predicate)? { - return BrilligSolver::::zero_out_brillig_outputs(witness, &brillig_pointer.outputs) - .map(|_| None); + return BrilligSolver::::zero_out_brillig_outputs(witness, outputs).map(|_| None); } // If we're resuming execution after resolving a foreign call then @@ -466,7 +466,7 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { } BrilligSolverStatus::Finished => { // Write execution outputs - solver.finalize(witness, &brillig_pointer.outputs)?; + solver.finalize(witness, outputs)?; Ok(None) } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index 9aa538e56081..c5c4554b0606 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -10,7 +10,7 @@ use crate::{ use acvm::acir::{ circuit::{ - brillig::{Brillig as AcvmBrillig, BrilligInputs, BrilligOutputs, BrilligPointer}, + brillig::{Brillig as AcvmBrillig, BrilligInputs, BrilligOutputs}, opcodes::{BlackBoxFuncCall, FunctionInput, Opcode as AcirOpcode}, OpcodeLocation, }, @@ -575,12 +575,8 @@ impl GeneratedAcir { outputs: Vec, brillig_function_index: u32, ) { - let opcode = AcirOpcode::BrilligPointer(BrilligPointer { - inputs, - outputs, - bytecode_index: brillig_function_index, - predicate, - }); + let opcode = + AcirOpcode::BrilligCall { id: brillig_function_index, inputs, outputs, predicate }; self.push_opcode(opcode); for (brillig_index, call_stack) in generated_brillig.locations.iter() { self.locations.insert( diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs index a2eb3c03d998..34963b4bea54 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs @@ -29,11 +29,18 @@ impl Ssa { let mut acir_index = 0; let mut brillig_index = 0; - let id_to_index = - btree_map(functions.iter().enumerate(), |(_, (id, func))| match func.runtime() { + let id_to_index = btree_map(functions.iter().enumerate(), |(_, (id, func))| { + let runtime = func.runtime(); + match func.runtime() { RuntimeType::Acir(_) => { let res = (*id, acir_index); - acir_index += 1; + // Any non-entry point ACIR function will be inlined into main + // so we do not want to increment on it. Otherwise we can possibly + // have ACIR function pointers that are larger than the total number of + // functions in a program. + if runtime.is_entry_point() || *id == main_id { + acir_index += 1; + } res } RuntimeType::Brillig => { @@ -41,7 +48,8 @@ impl Ssa { brillig_index += 1; res } - }); + } + }); Self { functions, main_id, next_id: AtomicCounter::starting_after(max_id), id_to_index } } diff --git a/noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/Nargo.toml b/noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/Nargo.toml new file mode 100644 index 000000000000..d23924af083b --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_after_inlined_calls" +type = "bin" +authors = [""] +compiler_version = ">=0.27.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/Prover.toml b/noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/Prover.toml new file mode 100644 index 000000000000..4dd6b4051592 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/Prover.toml @@ -0,0 +1 @@ +x = "1" diff --git a/noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/src/main.nr b/noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/src/main.nr new file mode 100644 index 000000000000..84c81190b9b6 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/src/main.nr @@ -0,0 +1,14 @@ +fn main(x: u32) { + // We want to call a foldable function after a call to a function that is set to be inlined + assert(increment(x) == x + 1); + foo(x); +} + +#[fold] +fn foo(x: u32) { + assert(x == 1); +} + +fn increment(x: u32) -> u32 { + x + 1 +} From 733eac078da8f6243e55e5586f4032bc3c47133c Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 15 Apr 2024 22:24:45 +0000 Subject: [PATCH 25/47] move to shraed context in acir gen --- .../src/brillig/brillig_ir/artifact.rs | 2 +- .../compiler/noirc_evaluator/src/ssa.rs | 8 +- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 2 +- .../ssa/acir_gen/acir_ir/generated_acir.rs | 1 + .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 99 ++++++++++++------- 5 files changed, 71 insertions(+), 41 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs index 8ce15ba4e73f..8bd1bfda78f3 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs @@ -17,7 +17,7 @@ pub(crate) enum BrilligParameter { /// The result of compiling and linking brillig artifacts. /// This is ready to run bytecode with attached metadata. -#[derive(Debug)] +#[derive(Debug, Default)] pub(crate) struct GeneratedBrillig { pub(crate) byte_code: Vec, pub(crate) locations: BTreeMap, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index 0c9b51a5b15c..3046b9906ac9 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -37,7 +37,9 @@ pub mod ssa_gen; /// Optimize the given program by converting it into SSA /// form and performing optimizations there. When finished, -/// convert the final SSA into ACIR and return it. +/// convert the final SSA into an ACIR program and return it. +/// An ACIR program is made up both separate ACIR functions +/// and separate Brillig functions for unconstrained execution. pub(crate) fn optimize_into_acir( program: Program, print_passes: bool, @@ -144,7 +146,7 @@ pub fn create_program( let func_sigs = program.function_signatures.clone(); let recursive = program.recursive; - let (generated_acirs, brillig_bytecode) = optimize_into_acir( + let (generated_acirs, generated_brilligs) = optimize_into_acir( program, enable_ssa_logging, enable_brillig_logging, @@ -157,7 +159,7 @@ pub fn create_program( "The generated ACIRs should match the supplied function signatures" ); - let mut program_artifact = SsaProgramArtifact::new(brillig_bytecode); + let mut program_artifact = SsaProgramArtifact::new(generated_brilligs); // For setting up the ABI we need separately specify main's input and return witnesses let mut is_main = true; for (acir, func_sig) in generated_acirs.into_iter().zip(func_sigs) { diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index d42a1bf306ac..9ae5c00e419b 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1463,6 +1463,7 @@ impl AcirContext { id } + // TODO: Delete this method once we remove the `Brillig` opcode pub(crate) fn brillig( &mut self, predicate: AcirVar, @@ -1564,7 +1565,6 @@ impl AcirContext { unsafe_return_values: bool, brillig_function_index: u32, ) -> Result, RuntimeError> { - // TODO: move this to its own method let b_inputs = try_vecmap(inputs, |i| -> Result<_, InternalError> { match i { AcirValue::Var(var, _) => Ok(BrilligInputs::Single(self.var_to_expression(var)?)), diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index c5c4554b0606..cd8c509ce976 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -539,6 +539,7 @@ impl GeneratedAcir { Ok(()) } + // TODO: Delete this method once we remove the `Brillig` opcode pub(crate) fn brillig( &mut self, predicate: Option, 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 b298c958eb88..abc3cdeff446 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 @@ -40,6 +40,45 @@ use im::Vector; use iter_extended::{try_vecmap, vecmap}; use noirc_frontend::Distinctness; +#[derive(Default)] +struct SharedContext { + /// Final list of Brillig functions which will be part of the final program + /// This is shared across `Context` structs as we want one list of Brillig + /// functions across all ACIR artifacts + generated_brilligs: Vec, + + /// Maps SSA function index -> Final generated Brillig artifact index. + /// Represents the index of a function from SSA to its final generated index. + /// There can be Brillig functions specified in SSA which do not act as + /// entry points in ACIR (e.g. only called by other Brillig functions) + /// This mapping is necessary to use the correct function pointer for a Brillig call. + brillig_generated_func_pointers: BTreeMap, +} + +impl SharedContext { + fn generated_brillig_pointer(&self, ssa_func_index: u32) -> Option<&u32> { + self.brillig_generated_func_pointers.get(&ssa_func_index) + } + + fn generated_brillig(&self, func_pointer: usize) -> &GeneratedBrillig { + &self.generated_brilligs[func_pointer] + } + + fn insert_generated_brillig( + &mut self, + ssa_func_index: u32, + generated_pointer: u32, + code: GeneratedBrillig, + ) { + self.brillig_generated_func_pointers.insert(ssa_func_index, generated_pointer); + self.generated_brilligs.push(code); + } + + fn new_generated_pointer(&self) -> u32 { + self.generated_brilligs.len() as u32 + } +} + /// Context struct for the acir generation pass. /// May be similar to the Evaluator struct in the current SSA IR. struct Context<'a> { @@ -93,18 +132,8 @@ struct Context<'a> { data_bus: DataBus, - /// Final list of Brillig functions which will be part of the final program - /// This is shared across `Context` structs as we want one list of Brillig - /// functions across all ACIR artifacts - generated_brilligs: &'a mut Vec, - - /// Maps SSA function index -> Final generated Brillig artifact index - /// Represents the index of a function from SSA to its final generated index. - /// There can be Brillig functions specified in SSA which do not act as - /// entry points in ACIR (e.g. only called by other Brillig functions) - /// We need this in case there are functions which have been specified in SSA - /// but ultimately were not used during ACIR gen - brillig_index_to_gen_index: &'a mut BTreeMap, + /// Contains state that is generated and also used across ACIR functions + shared_context: &'a mut SharedContext, } #[derive(Clone)] @@ -198,10 +227,9 @@ impl Ssa { ) -> Result<(Vec, Vec), RuntimeError> { let mut acirs = Vec::new(); // TODO: can we parallelise this? - let mut generated_brilligs = Vec::default(); - let mut brillig_index_to_gen_index = BTreeMap::default(); + let mut shared_context = SharedContext::default(); for function in self.functions.values() { - let context = Context::new(&mut generated_brilligs, &mut brillig_index_to_gen_index); + let context = Context::new(&mut shared_context); if let Some(mut generated_acir) = context.convert_ssa_function(&self, function, brillig)? { @@ -210,8 +238,9 @@ impl Ssa { } } - let brilligs = - vecmap(generated_brilligs, |brillig| BrilligBytecode { bytecode: brillig.byte_code }); + let brilligs = vecmap(shared_context.generated_brilligs, |brillig| BrilligBytecode { + bytecode: brillig.byte_code, + }); // TODO: check whether doing this for a single circuit's return witnesses is correct. // We probably need it for all foldable circuits, as any circuit being folded is essentially an entry point. However, I do not know how that @@ -242,10 +271,7 @@ impl Ssa { } impl<'a> Context<'a> { - fn new( - generated_brilligs: &'a mut Vec, - brillig_index_to_gen_index: &'a mut BTreeMap, - ) -> Context<'a> { + fn new(shared_context: &'a mut SharedContext) -> Context<'a> { let mut acir_context = AcirContext::default(); let current_side_effects_enabled_var = acir_context.add_constant(FieldElement::one()); @@ -259,8 +285,7 @@ impl<'a> Context<'a> { internal_mem_block_lengths: HashMap::default(), max_block_id: 0, data_bus: DataBus::default(), - generated_brilligs, - brillig_index_to_gen_index, + shared_context, } } @@ -622,7 +647,7 @@ impl<'a> Context<'a> { ); } } - let brillig_program_id = ssa + let brillig_ssa_id = *ssa .id_to_index .get(id) .expect("ICE: should have an associated final index"); @@ -633,10 +658,12 @@ impl<'a> Context<'a> { dfg.type_of_value(*result_id).into() }); - let output_values = if let Some(gen_index) = - self.brillig_index_to_gen_index.get(brillig_program_id) + let output_values = if let Some(generated_pointer) = + self.shared_context.generated_brillig_pointer(brillig_ssa_id) { - let code = &self.generated_brilligs[*gen_index as usize]; + let code = self + .shared_context + .generated_brillig(*generated_pointer as usize); self.acir_context.brillig_pointer( self.current_side_effects_enabled_var, code, @@ -644,14 +671,13 @@ impl<'a> Context<'a> { outputs, true, false, - *gen_index, + *generated_pointer, )? } else { let arguments = self.gen_brillig_parameters(arguments, dfg); let code = self.gen_brillig_for(func, arguments, brillig)?; - - let final_generated_index = - self.generated_brilligs.len() as u32; + let generated_pointer = + self.shared_context.new_generated_pointer(); let output_values = self.acir_context.brillig_pointer( self.current_side_effects_enabled_var, &code, @@ -659,12 +685,13 @@ impl<'a> Context<'a> { outputs, true, false, - final_generated_index, + generated_pointer, )?; - - self.brillig_index_to_gen_index - .insert(*brillig_program_id, final_generated_index); - self.generated_brilligs.push(code); + self.shared_context.insert_generated_brillig( + brillig_ssa_id, + generated_pointer, + code, + ); output_values }; From fba8b6e3df344b66f76f5fe37e1a245107039cdd Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 15 Apr 2024 22:30:10 +0000 Subject: [PATCH 26/47] cleanup --- noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs | 2 +- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 4 ++-- .../src/ssa/acir_gen/acir_ir/generated_acir.rs | 2 +- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 16 +++++++++------- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index 26716b65d3b5..fd6422e237bf 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -438,7 +438,7 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { }; let witness = &mut self.witness_map; - if is_predicate_false(witness, &predicate)? { + if is_predicate_false(witness, predicate)? { return BrilligSolver::::zero_out_brillig_outputs(witness, outputs).map(|_| None); } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 9ae5c00e419b..5deae8f32acb 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1555,7 +1555,7 @@ impl AcirContext { } #[allow(clippy::too_many_arguments)] - pub(crate) fn brillig_pointer( + pub(crate) fn brillig_call( &mut self, predicate: AcirVar, generated_brillig: &GeneratedBrillig, @@ -1611,7 +1611,7 @@ impl AcirContext { }); let predicate = self.var_to_expression(predicate)?; - self.acir_ir.brillig_pointer( + self.acir_ir.brillig_call( Some(predicate), generated_brillig, b_inputs, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index cd8c509ce976..3f8a490cd563 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -568,7 +568,7 @@ impl GeneratedAcir { } } - pub(crate) fn brillig_pointer( + pub(crate) fn brillig_call( &mut self, predicate: Option, generated_brillig: &GeneratedBrillig, 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 abc3cdeff446..63f163210e25 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 @@ -647,24 +647,26 @@ impl<'a> Context<'a> { ); } } - let brillig_ssa_id = *ssa - .id_to_index - .get(id) - .expect("ICE: should have an associated final index"); - let inputs = vecmap(arguments, |arg| self.convert_value(*arg, dfg)); let outputs: Vec = vecmap(result_ids, |result_id| { dfg.type_of_value(*result_id).into() }); + let brillig_ssa_id = *ssa + .id_to_index + .get(id) + .expect("ICE: should have an associated final index"); + + // Check whether we have already generated Brillig for this function + // If we have, re-use the generated code to set-up the brillig call. let output_values = if let Some(generated_pointer) = self.shared_context.generated_brillig_pointer(brillig_ssa_id) { let code = self .shared_context .generated_brillig(*generated_pointer as usize); - self.acir_context.brillig_pointer( + self.acir_context.brillig_call( self.current_side_effects_enabled_var, code, inputs, @@ -678,7 +680,7 @@ impl<'a> Context<'a> { let code = self.gen_brillig_for(func, arguments, brillig)?; let generated_pointer = self.shared_context.new_generated_pointer(); - let output_values = self.acir_context.brillig_pointer( + let output_values = self.acir_context.brillig_call( self.current_side_effects_enabled_var, &code, inputs, From f141f7b58f88814c73623984ffa482133eb73ff8 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 15 Apr 2024 22:31:59 +0000 Subject: [PATCH 27/47] cleanup comment in test --- .../execution_success/brillig_acir_loop/src/main.nr | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/src/main.nr index a5883e796069..7734b0a5353e 100644 --- a/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/src/main.nr @@ -1,8 +1,7 @@ fn main(x: Field, y: pub Field) { - // foo(x, y); for _ in 0..4 { foo(x, y); - // check_values(x, y); + check_values(x, y); } } From 32a151427e3c8ff3ce56d126c9450df615f6080e Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 15 Apr 2024 23:02:31 +0000 Subject: [PATCH 28/47] update serde --- .../src/barretenberg/dsl/acir_format/serde/acir.hpp | 12 ++++++------ noir/noir-repo/acvm-repo/acir/codegen/acir.cpp | 8 ++++---- .../compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp index 9910b7a68542..c32172a9319d 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp @@ -1124,9 +1124,9 @@ struct Opcode { }; struct BrilligCall { + uint32_t id; std::vector inputs; std::vector outputs; - uint32_t bytecode_index; std::optional predicate; friend bool operator==(const BrilligCall&, const BrilligCall&); @@ -7489,13 +7489,13 @@ namespace Program { inline bool operator==(const Opcode::BrilligCall& lhs, const Opcode::BrilligCall& rhs) { - if (!(lhs.inputs == rhs.inputs)) { + if (!(lhs.id == rhs.id)) { return false; } - if (!(lhs.outputs == rhs.outputs)) { + if (!(lhs.inputs == rhs.inputs)) { return false; } - if (!(lhs.bytecode_index == rhs.bytecode_index)) { + if (!(lhs.outputs == rhs.outputs)) { return false; } if (!(lhs.predicate == rhs.predicate)) { @@ -7528,9 +7528,9 @@ template void serde::Serializable::serialize(const Program::Opcode::BrilligCall& obj, Serializer& serializer) { + serde::Serializable::serialize(obj.id, serializer); serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); - serde::Serializable::serialize(obj.bytecode_index, serializer); serde::Serializable::serialize(obj.predicate, serializer); } @@ -7540,9 +7540,9 @@ Program::Opcode::BrilligCall serde::Deserializable Deserializer& deserializer) { Program::Opcode::BrilligCall obj; + obj.id = serde::Deserializable::deserialize(deserializer); obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); - obj.bytecode_index = serde::Deserializable::deserialize(deserializer); obj.predicate = serde::Deserializable::deserialize(deserializer); return obj; } diff --git a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp index 634faaac8033..c5dd097110c1 100644 --- a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp +++ b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp @@ -1062,9 +1062,9 @@ namespace Program { }; struct BrilligCall { + uint32_t id; std::vector inputs; std::vector outputs; - uint32_t bytecode_index; std::optional predicate; friend bool operator==(const BrilligCall&, const BrilligCall&); @@ -6183,9 +6183,9 @@ Program::Opcode::MemoryInit serde::Deserializable:: namespace Program { inline bool operator==(const Opcode::BrilligCall &lhs, const Opcode::BrilligCall &rhs) { + if (!(lhs.id == rhs.id)) { return false; } if (!(lhs.inputs == rhs.inputs)) { return false; } if (!(lhs.outputs == rhs.outputs)) { return false; } - if (!(lhs.bytecode_index == rhs.bytecode_index)) { return false; } if (!(lhs.predicate == rhs.predicate)) { return false; } return true; } @@ -6210,9 +6210,9 @@ namespace Program { template <> template void serde::Serializable::serialize(const Program::Opcode::BrilligCall &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.id, serializer); serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); - serde::Serializable::serialize(obj.bytecode_index, serializer); serde::Serializable::serialize(obj.predicate, serializer); } @@ -6220,9 +6220,9 @@ template <> template Program::Opcode::BrilligCall serde::Deserializable::deserialize(Deserializer &deserializer) { Program::Opcode::BrilligCall obj; + obj.id = serde::Deserializable::deserialize(deserializer); obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); - obj.bytecode_index = serde::Deserializable::deserialize(deserializer); obj.predicate = serde::Deserializable::deserialize(deserializer); return obj; } 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 63f163210e25..32bfa4805939 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 @@ -659,7 +659,7 @@ impl<'a> Context<'a> { .expect("ICE: should have an associated final index"); // Check whether we have already generated Brillig for this function - // If we have, re-use the generated code to set-up the brillig call. + // If we have, re-use the generated code to set-up the Brillig call. let output_values = if let Some(generated_pointer) = self.shared_context.generated_brillig_pointer(brillig_ssa_id) { From 78b8db0f066b4431e09dcd6875f3f8ba6ce043ef Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 16 Apr 2024 14:53:43 +0000 Subject: [PATCH 29/47] update instance delployer address --- yarn-project/circuits.js/src/constants.gen.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 70b3c4106e02..a1d483cbb44d 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 = 0x1674e9ab953fadc1d2140a5f9c8e36037f9b747001af69ba114df0c19d66bcb0n; +export const DEPLOYER_CONTRACT_ADDRESS = 0x2a8b73b47fede67a72dbacbedac49d4e6dd112380a2236cab18ea45383ce0b94n; 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; From 657180ecb7082142a3abd34872c94d59c1e5df52 Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Tue, 16 Apr 2024 16:05:35 +0100 Subject: [PATCH 30/47] Update noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs Co-authored-by: jfecher --- noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index 7fe03e22b721..5362af961a73 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -166,11 +166,7 @@ pub struct ACVM<'a, B: BlackBoxFunctionSolver> { /// List is appended onto by the caller upon reaching a [ACVMStatus::RequiresAcirCall] acir_call_results: Vec>, - // A counter maintained through an ACVM process that determines - // whether the caller has resolved the bytecode of a Brillig pointer - // brillig_call_counter: usize, - // Represents the bytecode pointer - // brillig_bytecodes: Vec< + // Each unconstrained function referenced in the program unconstrained_functions: &'a [BrilligBytecode], } From b36c53971e973a852e207b19399a752a5d35d7bf Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Tue, 16 Apr 2024 16:26:18 +0100 Subject: [PATCH 31/47] Update noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs Co-authored-by: jfecher --- noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index 3046b9906ac9..c79458541559 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -38,8 +38,8 @@ pub mod ssa_gen; /// Optimize the given program by converting it into SSA /// form and performing optimizations there. When finished, /// convert the final SSA into an ACIR program and return it. -/// An ACIR program is made up both separate ACIR functions -/// and separate Brillig functions for unconstrained execution. +/// An ACIR program is made up of both ACIR functions +/// and Brillig functions for unconstrained execution. pub(crate) fn optimize_into_acir( program: Program, print_passes: bool, From 5a838ee83fb638e36ed82a2d044fba39a63d06fe Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Tue, 16 Apr 2024 16:26:26 +0100 Subject: [PATCH 32/47] Update noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs Co-authored-by: jfecher --- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 5deae8f32acb..b3d52a2e05ec 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1569,10 +1569,9 @@ impl AcirContext { match i { AcirValue::Var(var, _) => Ok(BrilligInputs::Single(self.var_to_expression(var)?)), AcirValue::Array(vars) => { - let mut var_expressions: Vec = Vec::new(); - for var in vars { - self.brillig_array_input(&mut var_expressions, var)?; - } + let var_expressions = try_vecmap(vars, |var| { + self.brillig_array_input(&mut var_expressions, var) + })?; Ok(BrilligInputs::Array(var_expressions)) } AcirValue::DynamicArray(AcirDynamicArray { block_id, .. }) => { From 9bb92881276a51e602648667e0e1c69249c04fef Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Tue, 16 Apr 2024 16:26:55 +0100 Subject: [PATCH 33/47] Update noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs Co-authored-by: jfecher --- .../noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index b3d52a2e05ec..bd6e65b6465c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1565,7 +1565,7 @@ impl AcirContext { unsafe_return_values: bool, brillig_function_index: u32, ) -> Result, RuntimeError> { - let b_inputs = try_vecmap(inputs, |i| -> Result<_, InternalError> { + let brillig_inputs = try_vecmap(inputs, |i| -> Result<_, InternalError> { match i { AcirValue::Var(var, _) => Ok(BrilligInputs::Single(self.var_to_expression(var)?)), AcirValue::Array(vars) => { From ae0d8a91adaeea15db95fa45a90ab83271fe6209 Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Tue, 16 Apr 2024 16:27:01 +0100 Subject: [PATCH 34/47] Update noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs Co-authored-by: jfecher --- .../noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index bd6e65b6465c..9a92eadfd426 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1594,7 +1594,7 @@ impl AcirContext { } // Otherwise we must generate ACIR for it and execute at runtime. - let mut b_outputs = Vec::new(); + let mut brillig_outputs = Vec::new(); let outputs_var = vecmap(outputs, |output| match output { AcirType::NumericType(_) => { let witness_index = self.acir_ir.next_witness_index(); From c210697469c8a9d992b0b80ebcc86229f1a5ea23 Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Tue, 16 Apr 2024 16:27:08 +0100 Subject: [PATCH 35/47] Update noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs Co-authored-by: jfecher --- .../noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 9a92eadfd426..875a3db55c87 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1598,7 +1598,7 @@ impl AcirContext { let outputs_var = vecmap(outputs, |output| match output { AcirType::NumericType(_) => { let witness_index = self.acir_ir.next_witness_index(); - b_outputs.push(BrilligOutputs::Simple(witness_index)); + brillig_outputs.push(BrilligOutputs::Simple(witness_index)); let var = self.add_data(AcirVarData::Witness(witness_index)); AcirValue::Var(var, output.clone()) } From 368b7d88878c49854b2471d8d5244f1699a5c806 Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Tue, 16 Apr 2024 16:27:14 +0100 Subject: [PATCH 36/47] Update noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs Co-authored-by: jfecher --- .../noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 875a3db55c87..08c5c96614cd 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1604,7 +1604,7 @@ impl AcirContext { } AcirType::Array(element_types, size) => { let (acir_value, witnesses) = self.brillig_array_output(&element_types, size); - b_outputs.push(BrilligOutputs::Array(witnesses)); + brillig_outputs.push(BrilligOutputs::Array(witnesses)); acir_value } }); From 389da97031aa25636c9e444f9f21eec3ef61f4a0 Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Tue, 16 Apr 2024 16:27:21 +0100 Subject: [PATCH 37/47] Update noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs Co-authored-by: jfecher --- .../noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 08c5c96614cd..46832e41e409 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1613,8 +1613,8 @@ impl AcirContext { self.acir_ir.brillig_call( Some(predicate), generated_brillig, - b_inputs, - b_outputs, + brillig_inputs, + brillig_outputs, brillig_function_index, ); From a617ff54d6da3398e11cd028838bfb5b7bfa420a Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Tue, 16 Apr 2024 16:30:37 +0100 Subject: [PATCH 38/47] Update noir/noir-repo/cspell.json Co-authored-by: jfecher --- noir/noir-repo/cspell.json | 1 - 1 file changed, 1 deletion(-) diff --git a/noir/noir-repo/cspell.json b/noir/noir-repo/cspell.json index a75b49703dd6..16de9757fb88 100644 --- a/noir/noir-repo/cspell.json +++ b/noir/noir-repo/cspell.json @@ -27,7 +27,6 @@ "boilerplates", "bridgekeeper", "brillig", - "brilligs", "bytecount", "cachix", "callsite", From 3327c916f83cf8e309a44ccac04c48ba17a0e06f Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 16 Apr 2024 15:32:46 +0000 Subject: [PATCH 39/47] rename generated_brilligs --- noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs | 4 ++-- .../compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index c79458541559..760340f1a881 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -146,7 +146,7 @@ pub fn create_program( let func_sigs = program.function_signatures.clone(); let recursive = program.recursive; - let (generated_acirs, generated_brilligs) = optimize_into_acir( + let (generated_acirs, generated_brillig) = optimize_into_acir( program, enable_ssa_logging, enable_brillig_logging, @@ -159,7 +159,7 @@ pub fn create_program( "The generated ACIRs should match the supplied function signatures" ); - let mut program_artifact = SsaProgramArtifact::new(generated_brilligs); + let mut program_artifact = SsaProgramArtifact::new(generated_brillig); // For setting up the ABI we need separately specify main's input and return witnesses let mut is_main = true; for (acir, func_sig) in generated_acirs.into_iter().zip(func_sigs) { 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 c1a1f0aa2eb4..9a59b0a60a38 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 @@ -45,7 +45,7 @@ struct SharedContext { /// Final list of Brillig functions which will be part of the final program /// This is shared across `Context` structs as we want one list of Brillig /// functions across all ACIR artifacts - generated_brilligs: Vec, + generated_brillig: Vec, /// Maps SSA function index -> Final generated Brillig artifact index. /// Represents the index of a function from SSA to its final generated index. @@ -61,7 +61,7 @@ impl SharedContext { } fn generated_brillig(&self, func_pointer: usize) -> &GeneratedBrillig { - &self.generated_brilligs[func_pointer] + &self.generated_brillig[func_pointer] } fn insert_generated_brillig( @@ -71,11 +71,11 @@ impl SharedContext { code: GeneratedBrillig, ) { self.brillig_generated_func_pointers.insert(ssa_func_index, generated_pointer); - self.generated_brilligs.push(code); + self.generated_brillig.push(code); } fn new_generated_pointer(&self) -> u32 { - self.generated_brilligs.len() as u32 + self.generated_brillig.len() as u32 } } @@ -238,7 +238,7 @@ impl Ssa { } } - let brilligs = vecmap(shared_context.generated_brilligs, |brillig| BrilligBytecode { + let brilligs = vecmap(shared_context.generated_brillig, |brillig| BrilligBytecode { bytecode: brillig.byte_code, }); From 01c78c5bb2df850d2be3544f95a963215788ade1 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 16 Apr 2024 15:35:52 +0000 Subject: [PATCH 40/47] back to loop for brillig array input --- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 46832e41e409..8153da2e3317 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1569,9 +1569,10 @@ impl AcirContext { match i { AcirValue::Var(var, _) => Ok(BrilligInputs::Single(self.var_to_expression(var)?)), AcirValue::Array(vars) => { - let var_expressions = try_vecmap(vars, |var| { - self.brillig_array_input(&mut var_expressions, var) - })?; + let mut var_expressions: Vec = Vec::new(); + for var in vars { + self.brillig_array_input(&mut var_expressions, var)?; + } Ok(BrilligInputs::Array(var_expressions)) } AcirValue::DynamicArray(AcirDynamicArray { block_id, .. }) => { From 76b7b7a9919b74fde08a046891e2a19d4d55f96d Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 16 Apr 2024 15:46:22 +0000 Subject: [PATCH 41/47] missed name --- .../noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 8153da2e3317..3294eb166955 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1588,7 +1588,7 @@ impl AcirContext { // the entire program will be replaced with witness constraints to its outputs. if attempt_execution { if let Some(brillig_outputs) = - self.execute_brillig(&generated_brillig.byte_code, &b_inputs, &outputs) + self.execute_brillig(&generated_brillig.byte_code, &brillig_inputs, &outputs) { return Ok(brillig_outputs); } From 0aa917d685b0b969cf5c04565798e30b2d24be83 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 16 Apr 2024 16:46:45 +0000 Subject: [PATCH 42/47] label the entry point indices --- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 27 +++++------ .../src/ssa/ssa_gen/program.rs | 47 +++++++++---------- 2 files changed, 34 insertions(+), 40 deletions(-) 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 9a59b0a60a38..35a275b06454 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 @@ -7,6 +7,7 @@ use std::fmt::Debug; use self::acir_ir::acir_variable::{AcirContext, AcirType, AcirVar}; use super::function_builder::data_bus::DataBus; use super::ir::dfg::CallStack; +use super::ir::function::FunctionId; use super::ir::instruction::{ConstrainError, UserDefinedConstrainError}; use super::{ ir::{ @@ -48,16 +49,15 @@ struct SharedContext { generated_brillig: Vec, /// Maps SSA function index -> Final generated Brillig artifact index. - /// Represents the index of a function from SSA to its final generated index. /// There can be Brillig functions specified in SSA which do not act as /// entry points in ACIR (e.g. only called by other Brillig functions) /// This mapping is necessary to use the correct function pointer for a Brillig call. - brillig_generated_func_pointers: BTreeMap, + brillig_generated_func_pointers: BTreeMap, } impl SharedContext { - fn generated_brillig_pointer(&self, ssa_func_index: u32) -> Option<&u32> { - self.brillig_generated_func_pointers.get(&ssa_func_index) + fn generated_brillig_pointer(&self, func_id: &FunctionId) -> Option<&u32> { + self.brillig_generated_func_pointers.get(func_id) } fn generated_brillig(&self, func_pointer: usize) -> &GeneratedBrillig { @@ -66,11 +66,11 @@ impl SharedContext { fn insert_generated_brillig( &mut self, - ssa_func_index: u32, + func_id: FunctionId, generated_pointer: u32, code: GeneratedBrillig, ) { - self.brillig_generated_func_pointers.insert(ssa_func_index, generated_pointer); + self.brillig_generated_func_pointers.insert(func_id, generated_pointer); self.generated_brillig.push(code); } @@ -238,7 +238,7 @@ impl Ssa { } } - let brilligs = vecmap(shared_context.generated_brillig, |brillig| BrilligBytecode { + let brillig = vecmap(shared_context.generated_brillig, |brillig| BrilligBytecode { bytecode: brillig.byte_code, }); @@ -266,7 +266,7 @@ impl Ssa { } Distinctness::DuplicationAllowed => {} } - Ok((acirs, brilligs)) + Ok((acirs, brillig)) } } @@ -626,7 +626,7 @@ impl<'a> Context<'a> { }); let acir_program_id = ssa - .id_to_index + .entry_point_to_generated_index .get(id) .expect("ICE: should have an associated final index"); let output_vars = self.acir_context.call_acir_function( @@ -658,15 +658,10 @@ impl<'a> Context<'a> { dfg.type_of_value(*result_id).into() }); - let brillig_ssa_id = *ssa - .id_to_index - .get(id) - .expect("ICE: should have an associated final index"); - // Check whether we have already generated Brillig for this function // If we have, re-use the generated code to set-up the Brillig call. let output_values = if let Some(generated_pointer) = - self.shared_context.generated_brillig_pointer(brillig_ssa_id) + self.shared_context.generated_brillig_pointer(id) { let code = self .shared_context @@ -695,7 +690,7 @@ impl<'a> Context<'a> { generated_pointer, )?; self.shared_context.insert_generated_brillig( - brillig_ssa_id, + *id, generated_pointer, code, ); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs index 34963b4bea54..b05a2cbc7414 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs @@ -12,7 +12,11 @@ pub(crate) struct Ssa { pub(crate) functions: BTreeMap, pub(crate) main_id: FunctionId, pub(crate) next_id: AtomicCounter, - pub(crate) id_to_index: BTreeMap, + /// Maps SSA entry point function ID -> Final generated ACIR artifact index. + /// There can be functions specified in SSA which do not act as ACIR entry points. + /// This mapping is necessary to use the correct function pointer for an ACIR call, + /// as the final program artifact will be a list of only entry point functions. + pub(crate) entry_point_to_generated_index: BTreeMap, } impl Ssa { @@ -27,31 +31,26 @@ impl Ssa { (f.id(), f) }); - let mut acir_index = 0; - let mut brillig_index = 0; - let id_to_index = btree_map(functions.iter().enumerate(), |(_, (id, func))| { - let runtime = func.runtime(); - match func.runtime() { - RuntimeType::Acir(_) => { - let res = (*id, acir_index); - // Any non-entry point ACIR function will be inlined into main - // so we do not want to increment on it. Otherwise we can possibly - // have ACIR function pointers that are larger than the total number of - // functions in a program. - if runtime.is_entry_point() || *id == main_id { - acir_index += 1; + let entry_point_to_generated_index = btree_map( + functions + .iter() + .filter(|(_, func)| { + let runtime = func.runtime(); + match func.runtime() { + RuntimeType::Acir(_) => runtime.is_entry_point() || func.id() == main_id, + RuntimeType::Brillig => false, } - res - } - RuntimeType::Brillig => { - let res = (*id, brillig_index); - brillig_index += 1; - res - } - } - }); + }) + .enumerate(), + |(i, (id, _))| (*id, i as u32), + ); - Self { functions, main_id, next_id: AtomicCounter::starting_after(max_id), id_to_index } + Self { + functions, + main_id, + next_id: AtomicCounter::starting_after(max_id), + entry_point_to_generated_index, + } } /// Returns the entry-point function of the program From 7afebb6e1c7f242e87e1363ddc6889894dd68106 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 16 Apr 2024 18:55:42 +0000 Subject: [PATCH 43/47] add unit test for brilligcall gen and delete brillig_acir_loop --- .../src/brillig/brillig_gen/brillig_block.rs | 2 +- .../noirc_evaluator/src/brillig/brillig_ir.rs | 2 +- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 104 ++++++++++++++++-- .../brillig_acir_loop/Nargo.toml | 7 -- .../brillig_acir_loop/Prover.toml | 2 - .../brillig_acir_loop/src/main.nr | 14 --- 6 files changed, 97 insertions(+), 34 deletions(-) delete mode 100644 noir/noir-repo/test_programs/execution_success/brillig_acir_loop/Nargo.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/brillig_acir_loop/Prover.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/brillig_acir_loop/src/main.nr diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index 369d8e78cdaa..22407fc56959 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -1785,7 +1785,7 @@ pub(crate) fn type_of_binary_operation(lhs_type: &Type, rhs_type: &Type) -> Type (Type::Numeric(lhs_type), Type::Numeric(rhs_type)) => { assert_eq!( lhs_type, rhs_type, - "lhs and rhs types in a binary operation are always the same" + "lhs and rhs types in a binary operation are always the same but got {lhs_type} and {rhs_type}" ); Type::Numeric(*lhs_type) } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs index fdb03abe59f1..29210dc6f99c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs @@ -140,7 +140,7 @@ pub(crate) mod tests { &self, _public_key_x: &FieldElement, _public_key_y: &FieldElement, - _signature: &[u8], + _signature: &[u8; 64], _message: &[u8], ) -> Result { Ok(true) 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 35a275b06454..afd749485d7f 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 @@ -625,12 +625,12 @@ impl<'a> Context<'a> { sum + dfg.try_get_array_length(*result_id).unwrap_or(1) }); - let acir_program_id = ssa + let acir_function_id = ssa .entry_point_to_generated_index .get(id) .expect("ICE: should have an associated final index"); let output_vars = self.acir_context.call_acir_function( - *acir_program_id, + *acir_function_id, inputs, output_count, self.current_side_effects_enabled_var, @@ -2522,19 +2522,27 @@ mod test { }, }; - fn build_basic_foo_with_return(builder: &mut FunctionBuilder, foo_id: FunctionId) { - // acir(fold) fn foo f1 { + fn build_basic_foo_with_return( + builder: &mut FunctionBuilder, + foo_id: FunctionId, + is_brillig_func: bool, + ) { + // fn foo f1 { // b0(v0: Field, v1: Field): // v2 = eq v0, v1 // constrain v2 == u1 0 // return v0 // } - builder.new_function("foo".into(), foo_id, InlineType::Fold); + if is_brillig_func { + builder.new_brillig_function("foo".into(), foo_id); + } else { + builder.new_function("foo".into(), foo_id, InlineType::Fold); + } let foo_v0 = builder.add_parameter(Type::field()); let foo_v1 = builder.add_parameter(Type::field()); let foo_equality_check = builder.insert_binary(foo_v0, BinaryOp::Eq, foo_v1); - let zero = builder.field_constant(0u128); + let zero = builder.numeric_constant(0u128, Type::unsigned(1)); builder.insert_constrain(foo_equality_check, zero, None); builder.terminate_with_return(vec![foo_v0]); } @@ -2568,7 +2576,7 @@ mod test { builder.insert_constrain(main_call1_results[0], main_call2_results[0], None); builder.terminate_with_return(vec![]); - build_basic_foo_with_return(&mut builder, foo_id); + build_basic_foo_with_return(&mut builder, foo_id, false); let ssa = builder.finish(); @@ -2664,7 +2672,7 @@ mod test { builder.insert_constrain(main_call1_results[0], main_call2_results[0], None); builder.terminate_with_return(vec![]); - build_basic_foo_with_return(&mut builder, foo_id); + build_basic_foo_with_return(&mut builder, foo_id, false); let ssa = builder.finish(); @@ -2755,7 +2763,7 @@ mod test { .to_vec(); builder.terminate_with_return(vec![foo_call[0]]); - build_basic_foo_with_return(&mut builder, foo_id); + build_basic_foo_with_return(&mut builder, foo_id, false); let ssa = builder.finish(); @@ -2819,4 +2827,82 @@ mod test { _ => panic!("Expected only Call opcode"), } } + + // Test that given multiple calls to the same brillig function we generate only one bytecode + // and the appropriate Brillig call opcodes are generated + #[test] + fn multiple_brillig_calls_one_bytecode() { + // acir(inline) fn main f0 { + // b0(v0: Field, v1: Field): + // v3 = call f1(v0, v1) + // v4 = call f1(v0, v1) + // v5 = call f1(v0, v1) + // v6 = call f1(v0, v1) + // return + // } + // brillig fn foo f1 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == u1 0 + // return v0 + // } + // brillig fn foo f2 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == u1 0 + // return v0 + // } + let foo_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("main".into(), foo_id); + let main_v0 = builder.add_parameter(Type::field()); + let main_v1 = builder.add_parameter(Type::field()); + + let foo_id = Id::test_new(1); + let foo = builder.import_function(foo_id); + let bar_id = Id::test_new(2); + let bar = builder.import_function(bar_id); + + // Insert multiple calls to the same Brillig function + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + // Interleave a call to a separate Brillig function to make sure that we can call multiple separate Brillig functions + builder.insert_call(bar, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_call(bar, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.terminate_with_return(vec![]); + + build_basic_foo_with_return(&mut builder, foo_id, true); + build_basic_foo_with_return(&mut builder, bar_id, true); + + let ssa = builder.finish(); + let brillig = ssa.to_brillig(false); + println!("{}", ssa); + + let (acir_functions, brillig_functions) = ssa + .into_acir(&brillig, noirc_frontend::Distinctness::Distinct) + .expect("Should compile manually written SSA into ACIR"); + + assert_eq!(acir_functions.len(), 1, "Should only have a `main` ACIR function"); + assert_eq!( + brillig_functions.len(), + 2, + "Should only have generated a single Brillig function" + ); + + let main_acir = &acir_functions[0]; + let main_opcodes = main_acir.opcodes(); + assert_eq!(main_opcodes.len(), 6, "Should have four calls to f1 and two calls to f2"); + + // We should only have `BrilligCall` opcodes in `main` + for (i, opcode) in main_opcodes.iter().enumerate() { + match opcode { + Opcode::BrilligCall { id, .. } => { + let expected_id = if i == 3 || i == 5 { 1 } else { 0 }; + assert_eq!(*id, expected_id, "Expected an id of {expected_id} but got {id}"); + } + _ => panic!("Expected only Brillig call opcode"), + } + } + } } diff --git a/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/Nargo.toml b/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/Nargo.toml deleted file mode 100644 index 3ae4448bbcf7..000000000000 --- a/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/Nargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "brillig_acir_loop" -type = "bin" -authors = [""] -compiler_version = ">=0.26.0" - -[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/Prover.toml b/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/Prover.toml deleted file mode 100644 index f28f2f8cc48f..000000000000 --- a/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -x = "5" -y = "10" diff --git a/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/src/main.nr deleted file mode 100644 index 7734b0a5353e..000000000000 --- a/noir/noir-repo/test_programs/execution_success/brillig_acir_loop/src/main.nr +++ /dev/null @@ -1,14 +0,0 @@ -fn main(x: Field, y: pub Field) { - for _ in 0..4 { - foo(x, y); - check_values(x, y); - } -} - -unconstrained fn foo(x: Field, y: Field) { - check_values(x, y); -} - -unconstrained fn check_values(x: Field, y: Field) { - assert(x != y); -} From b93f30fa8a9b8b3ff8e07c33ee30308f988fffbf Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 16 Apr 2024 19:34:11 +0000 Subject: [PATCH 44/47] avm-transpiler needs to handle switch to brillig call opcode --- avm-transpiler/src/transpile.rs | 17 ++++++++--------- avm-transpiler/src/transpile_contract.rs | 7 +++---- avm-transpiler/src/utils.rs | 23 +++++++++++++++++------ 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/avm-transpiler/src/transpile.rs b/avm-transpiler/src/transpile.rs index 0de09a5793c5..8a39deebd658 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,12 @@ 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 537dfb34bb3d..a3c993146481 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,9 @@ 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 684dde7b6e4a..6044a880ab65 100644 --- a/avm-transpiler/src/utils.rs +++ b/avm-transpiler/src/utils.rs @@ -1,7 +1,8 @@ +use acvm::acir::brillig::Opcode as BrilligOpcode; use log::debug; -use acvm::acir::circuit::brillig::Brillig; -use acvm::acir::circuit::Opcode; +use acvm::acir::circuit::brillig::{Brillig, BrilligBytecode}; +use acvm::acir::circuit::{Opcode, Program}; use crate::instructions::AvmInstruction; @@ -20,14 +21,24 @@ pub fn extract_brillig_from_acir(opcodes: &Vec) -> &Brillig { } } +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 { id, .. } => {} + _ => 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 From a7795090886929d01cefbf20f9f511667d49c7ab Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 16 Apr 2024 19:52:18 +0000 Subject: [PATCH 45/47] update codegen for brillig main to use brillig call --- avm-transpiler/src/transpile.rs | 5 ++- avm-transpiler/src/utils.rs | 42 ++++++++++--------- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 8 +++- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/avm-transpiler/src/transpile.rs b/avm-transpiler/src/transpile.rs index 8a39deebd658..fda785f1ff9c 100644 --- a/avm-transpiler/src/transpile.rs +++ b/avm-transpiler/src/transpile.rs @@ -1089,7 +1089,10 @@ 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_bytecode: &[BrilligOpcode]) -> Vec { +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; diff --git a/avm-transpiler/src/utils.rs b/avm-transpiler/src/utils.rs index 6044a880ab65..2c39b9ae5e7c 100644 --- a/avm-transpiler/src/utils.rs +++ b/avm-transpiler/src/utils.rs @@ -1,35 +1,37 @@ use acvm::acir::brillig::Opcode as BrilligOpcode; use log::debug; -use acvm::acir::circuit::brillig::{Brillig, BrilligBytecode}; 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, - _ => panic!("Tried to extract a Brillig program from its ACIR wrapper opcode, but the opcode doesn't contain 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'"); + 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'"); + assert_eq!( + opcodes.len(), + 1, + "An AVM program should have only a single ACIR function flagged as 'BrilligCall'" + ); match opcodes[0] { - Opcode::BrilligCall { id, .. } => {} + 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"); + 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 } 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 afd749485d7f..8019707644bb 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()) From d315b0761ed303eed5863fc56d728fe420aa25cd Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 16 Apr 2024 20:09:38 +0000 Subject: [PATCH 46/47] cleanup --- avm-transpiler/src/transpile_contract.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm-transpiler/src/transpile_contract.rs b/avm-transpiler/src/transpile_contract.rs index a3c993146481..4cd7f350762e 100644 --- a/avm-transpiler/src/transpile_contract.rs +++ b/avm-transpiler/src/transpile_contract.rs @@ -90,7 +90,7 @@ impl From for TranspiledContract { let acir_program = function.bytecode; let brillig_bytecode = extract_brillig_from_acir_program(&acir_program); // Transpile to AVM - let avm_bytecode = brillig_to_avm(&brillig_bytecode); + let avm_bytecode = brillig_to_avm(brillig_bytecode); // Push modified function entry to ABI functions.push(AvmOrAcirContractFunction::Avm(AvmContractFunction { From 4952d98a51a32906c55f4aa98d0057e7d5fb15ee Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 16 Apr 2024 20:39:20 +0000 Subject: [PATCH 47/47] update instance deployer --- yarn-project/circuits.js/src/constants.gen.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index f3833975defe..223a3361fb4a 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;