diff --git a/.aztec-sync-commit b/.aztec-sync-commit index 8cfda4ff013..dc4d9c58bda 100644 --- a/.aztec-sync-commit +++ b/.aztec-sync-commit @@ -1 +1 @@ -d9de430e4a01d6908a9b1fe5e6ede9309aa8a10d +58761fcf181d0a26c4e387105b1bc8a3a75b0368 diff --git a/acvm-repo/acir/README.md b/acvm-repo/acir/README.md index 902769e3ad7..a0e7094b4d6 100644 --- a/acvm-repo/acir/README.md +++ b/acvm-repo/acir/README.md @@ -77,7 +77,7 @@ In summary, the workflow is the following: 1. user program -> (compilation) ACIR, a list of opcodes which constrain (partial) witnesses 2. user inputs + ACIR -> (execution/solving) assign values to all the - (partial) witnesses + (partial) witnesses 3. witness assignment + ACIR -> (proving system) proof Although the ordering of opcode does not matter in theory, since a system of @@ -121,7 +121,7 @@ proving system and are only used by the solver. Finally, some opcodes will have a predicate, whose value is `0` or `1`. Its purpose is to nullify the opcode when the value is `0`, so that it has no effect. Note that removing the opcode is not a solution because this modifies -the circuit (the circuit being mainly the list of the opcodes). +the circuit (the circuit being mainly the list of the opcodes). *Remark*: Opcodes operate on witnesses, but we will see that some opcode work on expressions of witnesses. We call an expression a linear combination of @@ -265,16 +265,6 @@ without adding any constraint. NOTE: see the [circuit/opcodes.rs](src/circuit/opcodes.rs) file for the most up-to-date documentation on these opcodes. -#### Directive - -This opcode is a specialization of Brillig opcode. Instead of having some generic -assembly code like Brillig, a directive has a hardcoded name which tells the -solver which computation to do: with Brillig, the computation refers to the -compiled bytecode of an unconstrained Noir function, but with a directive, the -computation is hardcoded inside the compiler. - -Directives will be replaced by Brillig opcodes in the future. - #### MemoryOp: memory abstraction for ACIR ACIR is able to address any array of witnesses. Each array is assigned an ID diff --git a/acvm-repo/acir/benches/serialization.rs b/acvm-repo/acir/benches/serialization.rs index 792200c8912..dd6a5c8b1cf 100644 --- a/acvm-repo/acir/benches/serialization.rs +++ b/acvm-repo/acir/benches/serialization.rs @@ -38,7 +38,6 @@ fn sample_program(num_opcodes: usize) -> Program { public_parameters: PublicInputs(BTreeSet::from([Witness(5)])), return_values: PublicInputs(BTreeSet::from([Witness(6)])), assert_messages: Vec::new(), - recursive: false, }], unconstrained_functions: Vec::new(), } diff --git a/acvm-repo/acir/codegen/acir.cpp b/acvm-repo/acir/codegen/acir.cpp index 0880b5a0cbe..2ae9a31d6ca 100644 --- a/acvm-repo/acir/codegen/acir.cpp +++ b/acvm-repo/acir/codegen/acir.cpp @@ -702,8 +702,7 @@ namespace Program { }; struct Stop { - uint64_t return_data_offset; - uint64_t return_data_size; + Program::HeapVector return_data; friend bool operator==(const Stop&, const Stop&); std::vector bincodeSerialize() const; @@ -1086,25 +1085,6 @@ namespace Program { static BrilligOutputs bincodeDeserialize(std::vector); }; - struct Directive { - - struct ToLeRadix { - Program::Expression a; - std::vector b; - uint32_t radix; - - friend bool operator==(const ToLeRadix&, const ToLeRadix&); - std::vector bincodeSerialize() const; - static ToLeRadix bincodeDeserialize(std::vector); - }; - - std::variant value; - - friend bool operator==(const Directive&, const Directive&); - std::vector bincodeSerialize() const; - static Directive bincodeDeserialize(std::vector); - }; - struct MemOp { Program::Expression operation; Program::Expression index; @@ -1133,14 +1113,6 @@ namespace Program { static BlackBoxFuncCall bincodeDeserialize(std::vector); }; - struct Directive { - Program::Directive value; - - friend bool operator==(const Directive&, const Directive&); - std::vector bincodeSerialize() const; - static Directive bincodeDeserialize(std::vector); - }; - struct MemoryOp { Program::BlockId block_id; Program::MemOp op; @@ -1183,7 +1155,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; @@ -1216,24 +1188,8 @@ namespace Program { }; struct AssertionPayload { - - struct StaticString { - std::string value; - - friend bool operator==(const StaticString&, const StaticString&); - std::vector bincodeSerialize() const; - static StaticString bincodeDeserialize(std::vector); - }; - - struct Dynamic { - std::tuple> value; - - friend bool operator==(const Dynamic&, const Dynamic&); - std::vector bincodeSerialize() const; - static Dynamic bincodeDeserialize(std::vector); - }; - - std::variant value; + uint64_t error_selector; + std::vector payload; friend bool operator==(const AssertionPayload&, const AssertionPayload&); std::vector bincodeSerialize() const; @@ -1305,7 +1261,6 @@ namespace Program { Program::PublicInputs public_parameters; Program::PublicInputs return_values; std::vector> assert_messages; - bool recursive; friend bool operator==(const Circuit&, const Circuit&); std::vector bincodeSerialize() const; @@ -1335,7 +1290,8 @@ namespace Program { namespace Program { inline bool operator==(const AssertionPayload &lhs, const AssertionPayload &rhs) { - if (!(lhs.value == rhs.value)) { return false; } + if (!(lhs.error_selector == rhs.error_selector)) { return false; } + if (!(lhs.payload == rhs.payload)) { return false; } return true; } @@ -1360,7 +1316,8 @@ template <> template void serde::Serializable::serialize(const Program::AssertionPayload &obj, Serializer &serializer) { serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); + serde::Serializable::serialize(obj.error_selector, serializer); + serde::Serializable::serialize(obj.payload, serializer); serializer.decrease_container_depth(); } @@ -1369,87 +1326,12 @@ template Program::AssertionPayload serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); Program::AssertionPayload obj; - obj.value = serde::Deserializable::deserialize(deserializer); + obj.error_selector = serde::Deserializable::deserialize(deserializer); + obj.payload = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { - - inline bool operator==(const AssertionPayload::StaticString &lhs, const AssertionPayload::StaticString &rhs) { - if (!(lhs.value == rhs.value)) { return false; } - return true; - } - - inline std::vector AssertionPayload::StaticString::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline AssertionPayload::StaticString AssertionPayload::StaticString::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::AssertionPayload::StaticString &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); -} - -template <> -template -Program::AssertionPayload::StaticString serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::AssertionPayload::StaticString obj; - obj.value = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Program { - - inline bool operator==(const AssertionPayload::Dynamic &lhs, const AssertionPayload::Dynamic &rhs) { - if (!(lhs.value == rhs.value)) { return false; } - return true; - } - - inline std::vector AssertionPayload::Dynamic::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline AssertionPayload::Dynamic AssertionPayload::Dynamic::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::AssertionPayload::Dynamic &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); -} - -template <> -template -Program::AssertionPayload::Dynamic serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::AssertionPayload::Dynamic obj; - obj.value = serde::Deserializable::deserialize(deserializer); - return obj; -} - namespace Program { inline bool operator==(const BinaryFieldOp &lhs, const BinaryFieldOp &rhs) { @@ -5423,8 +5305,7 @@ Program::BrilligOpcode::Trap serde::Deserializable namespace Program { inline bool operator==(const BrilligOpcode::Stop &lhs, const BrilligOpcode::Stop &rhs) { - if (!(lhs.return_data_offset == rhs.return_data_offset)) { return false; } - if (!(lhs.return_data_size == rhs.return_data_size)) { return false; } + if (!(lhs.return_data == rhs.return_data)) { return false; } return true; } @@ -5448,16 +5329,14 @@ namespace Program { template <> template void serde::Serializable::serialize(const Program::BrilligOpcode::Stop &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.return_data_offset, serializer); - serde::Serializable::serialize(obj.return_data_size, serializer); + serde::Serializable::serialize(obj.return_data, serializer); } template <> template Program::BrilligOpcode::Stop serde::Deserializable::deserialize(Deserializer &deserializer) { Program::BrilligOpcode::Stop obj; - obj.return_data_offset = serde::Deserializable::deserialize(deserializer); - obj.return_data_size = serde::Deserializable::deserialize(deserializer); + obj.return_data = serde::Deserializable::deserialize(deserializer); return obj; } @@ -5589,7 +5468,6 @@ namespace Program { if (!(lhs.public_parameters == rhs.public_parameters)) { return false; } if (!(lhs.return_values == rhs.return_values)) { return false; } if (!(lhs.assert_messages == rhs.assert_messages)) { return false; } - if (!(lhs.recursive == rhs.recursive)) { return false; } return true; } @@ -5621,7 +5499,6 @@ void serde::Serializable::serialize(const Program::Circuit &ob serde::Serializable::serialize(obj.public_parameters, serializer); serde::Serializable::serialize(obj.return_values, serializer); serde::Serializable::serialize(obj.assert_messages, serializer); - serde::Serializable::serialize(obj.recursive, serializer); serializer.decrease_container_depth(); } @@ -5637,7 +5514,6 @@ Program::Circuit serde::Deserializable::deserialize(Deserializ obj.public_parameters = serde::Deserializable::deserialize(deserializer); obj.return_values = serde::Deserializable::deserialize(deserializer); obj.assert_messages = serde::Deserializable::deserialize(deserializer); - obj.recursive = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } @@ -5760,92 +5636,6 @@ Program::ConstantOrWitnessEnum::Witness serde::Deserializable Directive::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline Directive Directive::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::Directive &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); -} - -template <> -template -Program::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::Directive obj; - obj.value = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; -} - -namespace Program { - - inline bool operator==(const Directive::ToLeRadix &lhs, const Directive::ToLeRadix &rhs) { - if (!(lhs.a == rhs.a)) { return false; } - if (!(lhs.b == rhs.b)) { return false; } - if (!(lhs.radix == rhs.radix)) { return false; } - return true; - } - - inline std::vector Directive::ToLeRadix::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline Directive::ToLeRadix Directive::ToLeRadix::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::Directive::ToLeRadix &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.a, serializer); - serde::Serializable::serialize(obj.b, serializer); - serde::Serializable::serialize(obj.radix, serializer); -} - -template <> -template -Program::Directive::ToLeRadix serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::Directive::ToLeRadix obj; - obj.a = serde::Deserializable::deserialize(deserializer); - obj.b = serde::Deserializable::deserialize(deserializer); - obj.radix = serde::Deserializable::deserialize(deserializer); - return obj; -} - namespace Program { inline bool operator==(const Expression &lhs, const Expression &rhs) { @@ -6957,44 +6747,6 @@ Program::Opcode::BlackBoxFuncCall serde::Deserializable Opcode::Directive::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline Opcode::Directive Opcode::Directive::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::Directive &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); -} - -template <> -template -Program::Opcode::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::Opcode::Directive obj; - obj.value = serde::Deserializable::deserialize(deserializer); - return obj; -} - namespace Program { inline bool operator==(const Opcode::MemoryOp &lhs, const Opcode::MemoryOp &rhs) { diff --git a/acvm-repo/acir/src/circuit/directives.rs b/acvm-repo/acir/src/circuit/directives.rs deleted file mode 100644 index 3bc66288590..00000000000 --- a/acvm-repo/acir/src/circuit/directives.rs +++ /dev/null @@ -1,11 +0,0 @@ -use crate::native_types::{Expression, Witness}; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -/// Directives do not apply any constraints. -/// You can think of them as opcodes that allow one to use non-determinism -/// In the future, this can be replaced with asm non-determinism blocks -pub enum Directive { - //decomposition of a: a=\sum b[i]*radix^i where b is an array of witnesses < radix in little endian form - ToLeRadix { a: Expression, b: Vec, radix: u32 }, -} diff --git a/acvm-repo/acir/src/circuit/mod.rs b/acvm-repo/acir/src/circuit/mod.rs index f700fefe0cd..33982065c2a 100644 --- a/acvm-repo/acir/src/circuit/mod.rs +++ b/acvm-repo/acir/src/circuit/mod.rs @@ -1,6 +1,5 @@ pub mod black_box_functions; pub mod brillig; -pub mod directives; pub mod opcodes; use crate::native_types::{Expression, Witness}; @@ -68,11 +67,6 @@ pub struct Circuit { // c++ code at the moment when it is, due to OpcodeLocation needing a comparison // implementation which is never generated. pub assert_messages: Vec<(OpcodeLocation, AssertionPayload)>, - - /// States whether the backend should use a SNARK recursion friendly prover. - /// If implemented by a backend, this means that proofs generated with this circuit - /// will be friendly for recursively verifying inside of another SNARK. - pub recursive: bool, } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] @@ -82,9 +76,9 @@ pub enum ExpressionOrMemory { } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum AssertionPayload { - StaticString(String), - Dynamic(/* error_selector */ u64, Vec>), +pub struct AssertionPayload { + pub error_selector: u64, + pub payload: Vec>, } #[derive(Debug, Copy, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)] @@ -120,12 +114,6 @@ impl<'de> Deserialize<'de> for ErrorSelector { } } -/// This selector indicates that the payload is a string. -/// This is used to parse any error with a string payload directly, -/// to avoid users having to parse the error externally to the ACVM. -/// Only non-string errors need to be parsed externally to the ACVM using the circuit ABI. -pub const STRING_ERROR_SELECTOR: ErrorSelector = ErrorSelector(0); - #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] pub struct RawAssertionPayload { pub selector: ErrorSelector, @@ -445,7 +433,6 @@ mod tests { public_parameters: PublicInputs(BTreeSet::from_iter(vec![Witness(2), Witness(12)])), return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(4), Witness(12)])), assert_messages: Default::default(), - recursive: false, }; let program = Program { functions: vec![circuit], unconstrained_functions: Vec::new() }; @@ -481,7 +468,6 @@ mod tests { public_parameters: PublicInputs(BTreeSet::from_iter(vec![Witness(2)])), return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(2)])), assert_messages: Default::default(), - recursive: false, }; let program = Program { functions: vec![circuit], unconstrained_functions: Vec::new() }; diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index 848d7bda84b..06effd3c5b6 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -1,7 +1,4 @@ -use super::{ - brillig::{BrilligFunctionId, BrilligInputs, BrilligOutputs}, - directives::Directive, -}; +use super::brillig::{BrilligFunctionId, BrilligInputs, BrilligOutputs}; pub mod function_id; pub use function_id::AcirFunctionId; @@ -60,7 +57,7 @@ pub enum Opcode { /// specialized constraints. /// /// Often used for exposing more efficient implementations of - /// SNARK-unfriendly computations. + /// SNARK-unfriendly computations. /// /// All black box functions take as input a tuple `(witness, num_bits)`, /// where `num_bits` is a constant representing the bit size of the input @@ -75,16 +72,6 @@ pub enum Opcode { /// embedded curve. BlackBoxFuncCall(BlackBoxFuncCall), - /// This opcode is a specialization of a Brillig opcode. Instead of having - /// some generic assembly code like Brillig, a directive has a hardcoded - /// name which tells the solver which computation to do: with Brillig, the - /// computation refers to the compiled bytecode of an unconstrained Noir - /// function, but with a directive, the computation is hardcoded inside the - /// compiler. - /// - /// Directives will be replaced by Brillig opcodes in the future. - Directive(Directive), - /// Atomic operation on a block of memory /// /// ACIR is able to address any array of witnesses. Each array is assigned @@ -158,18 +145,6 @@ impl std::fmt::Display for Opcode { } Opcode::BlackBoxFuncCall(g) => write!(f, "{g}"), - Opcode::Directive(Directive::ToLeRadix { a, b, radix: _ }) => { - write!(f, "DIR::TORADIX ")?; - write!( - f, - // TODO (Note): this assumes that the decomposed bits have contiguous witness indices - // This should be the case, however, we can also have a function which checks this - "(_{}, [_{}..._{}] )", - a, - b.first().unwrap().witness_index(), - b.last().unwrap().witness_index(), - ) - } Opcode::MemoryOp { block_id, op, predicate } => { write!(f, "MEM ")?; if let Some(pred) = predicate { diff --git a/acvm-repo/acir/src/lib.rs b/acvm-repo/acir/src/lib.rs index f8a31439127..bb5b50c0daf 100644 --- a/acvm-repo/acir/src/lib.rs +++ b/acvm-repo/acir/src/lib.rs @@ -42,7 +42,6 @@ mod reflection { use crate::{ circuit::{ brillig::{BrilligInputs, BrilligOutputs}, - directives::Directive, opcodes::{BlackBoxFuncCall, BlockType, ConstantOrWitnessEnum, FunctionInput}, AssertionPayload, Circuit, ExpressionOrMemory, ExpressionWidth, Opcode, OpcodeLocation, Program, @@ -77,7 +76,6 @@ mod reflection { tracer.trace_simple_type::>().unwrap(); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); - tracer.trace_simple_type::>().unwrap(); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::>().unwrap(); diff --git a/acvm-repo/acir/tests/test_program_serialization.rs b/acvm-repo/acir/tests/test_program_serialization.rs index a915cb95d07..002bad0e7f3 100644 --- a/acvm-repo/acir/tests/test_program_serialization.rs +++ b/acvm-repo/acir/tests/test_program_serialization.rs @@ -20,7 +20,9 @@ use acir::{ native_types::{Expression, Witness}, }; use acir_field::{AcirField, FieldElement}; -use brillig::{BitSize, HeapArray, HeapValueType, IntegerBitSize, MemoryAddress, ValueOrArray}; +use brillig::{ + BitSize, HeapArray, HeapValueType, HeapVector, IntegerBitSize, MemoryAddress, ValueOrArray, +}; #[test] fn addition_circuit() { @@ -47,11 +49,11 @@ fn addition_circuit() { let expected_serialization: Vec = vec![ 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, + 104, 111, 126, 69, 34, 252, 255, 9, 106, 228, 64, 194, 81, 38, 105, 182, 167, 201, 102, + 189, 251, 216, 159, 243, 110, 38, 244, 60, 122, 194, 63, 208, 47, 116, 109, 131, 139, 32, + 49, 215, 28, 43, 18, 158, 16, 173, 168, 0, 75, 73, 138, 138, 162, 114, 69, 37, 170, 202, + 154, 173, 88, 6, 67, 166, 138, 77, 140, 90, 151, 133, 117, 189, 224, 117, 108, 221, 229, + 135, 223, 13, 27, 135, 121, 106, 119, 3, 58, 173, 124, 163, 140, 1, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -91,10 +93,10 @@ fn multi_scalar_mul_circuit() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 77, 9, 14, 0, 32, 8, 202, 171, 227, 255, 255, 109, - 217, 162, 141, 114, 99, 2, 162, 74, 57, 53, 18, 2, 46, 208, 70, 122, 99, 162, 43, 113, 35, - 239, 102, 157, 230, 1, 94, 19, 45, 209, 145, 11, 202, 43, 238, 56, 249, 133, 254, 255, 187, - 79, 45, 204, 84, 220, 246, 193, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 77, 9, 10, 0, 32, 8, 243, 236, 248, 255, 127, 35, + 163, 5, 35, 97, 184, 205, 169, 42, 183, 102, 65, 193, 21, 218, 73, 31, 44, 116, 35, 238, + 228, 189, 108, 208, 60, 193, 91, 161, 23, 6, 114, 73, 121, 195, 157, 32, 95, 232, 255, 191, + 203, 181, 1, 243, 231, 24, 106, 192, 0, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -134,24 +136,24 @@ 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, 85, 211, 103, 78, 2, 81, 24, 70, 225, 193, 130, 96, 239, - 189, 96, 239, 189, 35, 34, 34, 34, 34, 238, 130, 253, 47, 129, 192, 9, 223, 36, 7, 146, - 201, 60, 209, 31, 144, 123, 207, 155, 73, 250, 159, 118, 239, 201, 132, 121, 103, 227, 205, - 211, 137, 247, 144, 60, 220, 123, 114, 225, 17, 121, 84, 206, 202, 99, 114, 78, 206, 203, - 227, 242, 132, 60, 41, 79, 201, 211, 242, 140, 60, 43, 207, 201, 243, 242, 130, 188, 40, - 47, 201, 203, 242, 138, 188, 42, 175, 201, 235, 242, 134, 188, 41, 111, 201, 219, 242, 142, - 92, 144, 119, 229, 61, 121, 95, 62, 144, 15, 229, 35, 249, 88, 62, 145, 79, 229, 51, 249, - 92, 190, 144, 47, 229, 43, 249, 90, 190, 145, 111, 229, 59, 249, 94, 126, 144, 31, 229, 39, - 249, 89, 126, 145, 95, 229, 162, 252, 38, 151, 228, 119, 185, 44, 127, 200, 21, 249, 83, - 174, 134, 233, 52, 137, 191, 125, 233, 255, 53, 249, 91, 174, 203, 63, 114, 67, 254, 149, - 155, 242, 159, 220, 10, 255, 199, 247, 183, 244, 59, 216, 38, 155, 100, 139, 108, 144, 237, - 165, 155, 203, 199, 111, 102, 83, 108, 137, 13, 177, 29, 54, 195, 86, 216, 8, 219, 96, 19, - 108, 129, 13, 208, 62, 205, 211, 58, 141, 211, 54, 77, 211, 50, 13, 211, 46, 205, 22, 146, - 126, 163, 180, 73, 147, 180, 72, 131, 180, 71, 115, 180, 70, 99, 180, 69, 83, 180, 68, 67, - 180, 67, 51, 180, 66, 35, 180, 65, 19, 180, 64, 3, 220, 61, 119, 206, 93, 115, 199, 197, - 184, 211, 82, 220, 97, 57, 238, 172, 18, 119, 84, 141, 187, 168, 197, 217, 215, 227, 172, - 27, 113, 182, 205, 56, 203, 244, 204, 210, 115, 75, 116, 158, 3, 159, 46, 43, 32, 188, 53, - 25, 5, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 211, 103, 78, 2, 81, 24, 70, 225, 193, 130, 96, 239, + 189, 96, 239, 189, 35, 34, 34, 34, 82, 118, 193, 254, 151, 64, 224, 132, 111, 146, 67, 50, + 153, 39, 250, 3, 114, 239, 121, 51, 201, 240, 211, 29, 60, 153, 48, 239, 108, 188, 121, + 122, 241, 30, 145, 71, 7, 79, 46, 60, 38, 143, 203, 89, 121, 66, 206, 201, 121, 121, 82, + 158, 146, 167, 229, 25, 121, 86, 158, 147, 231, 229, 5, 121, 81, 94, 146, 151, 229, 21, + 121, 85, 94, 147, 215, 229, 13, 121, 83, 222, 146, 183, 229, 29, 121, 87, 222, 147, 11, + 242, 190, 124, 32, 31, 202, 71, 242, 177, 124, 34, 159, 202, 103, 242, 185, 124, 33, 95, + 202, 87, 242, 181, 124, 35, 223, 202, 119, 242, 189, 252, 32, 63, 202, 79, 242, 179, 252, + 34, 191, 202, 111, 242, 187, 92, 148, 63, 228, 146, 252, 41, 151, 229, 47, 185, 34, 127, + 203, 213, 48, 157, 38, 241, 183, 31, 253, 191, 38, 255, 202, 117, 249, 79, 110, 200, 255, + 114, 83, 110, 201, 237, 112, 39, 190, 191, 173, 223, 193, 54, 217, 36, 91, 100, 131, 108, + 47, 221, 92, 62, 126, 51, 155, 98, 75, 108, 136, 237, 176, 25, 182, 194, 70, 216, 6, 155, + 96, 11, 108, 128, 246, 105, 158, 214, 105, 156, 182, 105, 154, 150, 105, 152, 118, 105, + 182, 144, 12, 27, 165, 77, 154, 164, 69, 26, 164, 61, 154, 163, 53, 26, 163, 45, 154, 162, + 37, 26, 162, 29, 154, 161, 21, 26, 161, 13, 154, 160, 5, 26, 224, 238, 185, 115, 238, 154, + 59, 46, 198, 157, 150, 226, 14, 203, 113, 103, 149, 184, 163, 106, 220, 69, 45, 206, 190, + 30, 103, 221, 136, 179, 109, 198, 89, 166, 103, 150, 158, 91, 162, 243, 244, 167, 15, 14, + 161, 226, 6, 24, 5, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -162,31 +164,37 @@ fn simple_brillig_foreign_call() { let w_input = Witness(1); let w_inverted = Witness(2); + let value_address = MemoryAddress::direct(0); + let zero_usize = MemoryAddress::direct(1); + let one_usize = MemoryAddress::direct(2); + let brillig_bytecode = BrilligBytecode { bytecode: vec![ brillig::Opcode::Const { - destination: MemoryAddress::direct(0), + destination: zero_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(1_usize), + value: FieldElement::from(0_usize), }, brillig::Opcode::Const { - destination: MemoryAddress::direct(1), + destination: one_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(0_usize), + value: FieldElement::from(1_usize), }, brillig::Opcode::CalldataCopy { - destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + destination_address: value_address, + size_address: one_usize, + offset_address: zero_usize, }, brillig::Opcode::ForeignCall { function: "invert".into(), - destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(0))], + destinations: vec![ValueOrArray::MemoryAddress(value_address)], destination_value_types: vec![HeapValueType::field()], - inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(0))], + inputs: vec![ValueOrArray::MemoryAddress(value_address)], input_value_types: vec![HeapValueType::field()], }, - brillig::Opcode::Stop { return_data_offset: 0, return_data_size: 1 }, + brillig::Opcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: one_usize }, + }, ], }; @@ -214,12 +222,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, 79, 73, 10, 128, 48, 12, 204, 40, 46, 5, 111, 126, - 36, 254, 192, 207, 120, 240, 226, 65, 196, 247, 91, 48, 129, 80, 218, 122, 48, 3, 33, 147, - 9, 89, 6, 244, 98, 140, 1, 225, 157, 100, 173, 45, 84, 91, 37, 243, 63, 44, 240, 219, 197, - 246, 223, 38, 37, 176, 34, 85, 156, 169, 251, 144, 233, 183, 142, 206, 67, 114, 215, 121, - 63, 15, 84, 135, 222, 157, 98, 244, 194, 247, 227, 222, 206, 11, 31, 19, 165, 186, 164, - 207, 153, 222, 3, 91, 101, 84, 220, 120, 2, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 81, 203, 10, 128, 48, 12, 179, 243, 57, 240, 230, + 143, 108, 127, 224, 207, 120, 240, 226, 65, 196, 239, 119, 98, 11, 101, 100, 94, 214, 64, + 73, 26, 88, 73, 24, 53, 31, 166, 52, 196, 186, 99, 150, 93, 67, 188, 149, 57, 212, 33, 146, + 221, 173, 160, 243, 186, 92, 144, 54, 127, 138, 245, 204, 62, 243, 95, 110, 13, 195, 122, + 144, 207, 240, 126, 28, 65, 71, 7, 250, 206, 105, 6, 214, 251, 113, 111, 231, 133, 190, 93, + 191, 40, 237, 37, 127, 1, 190, 36, 121, 0, 128, 254, 118, 42, 127, 2, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -304,7 +312,22 @@ fn complex_brillig_foreign_call() { HeapValueType::field(), ], }, - brillig::Opcode::Stop { return_data_offset: 32, return_data_size: 5 }, + brillig::Opcode::Const { + destination: MemoryAddress::direct(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(32_usize), + }, + brillig::Opcode::Const { + destination: MemoryAddress::direct(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(5_usize), + }, + brillig::Opcode::Stop { + return_data: HeapVector { + pointer: MemoryAddress::direct(0), + size: MemoryAddress::direct(1), + }, + }, ], }; @@ -344,17 +367,17 @@ 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, 85, 93, 10, 194, 48, 12, 78, 155, 233, 54, 240, - 205, 11, 8, 122, 128, 76, 47, 176, 187, 136, 111, 138, 62, 122, 124, 45, 75, 88, 23, 139, - 19, 76, 64, 63, 24, 89, 75, 242, 229, 159, 6, 24, 208, 60, 191, 192, 255, 11, 150, 145, - 101, 186, 71, 152, 66, 116, 123, 150, 244, 29, 186, 96, 199, 69, 94, 49, 198, 63, 136, 17, - 29, 98, 132, 172, 255, 63, 216, 111, 203, 190, 152, 214, 15, 11, 251, 83, 193, 176, 95, 75, - 62, 215, 44, 27, 93, 232, 100, 20, 225, 117, 241, 38, 144, 233, 105, 149, 4, 229, 185, 183, - 201, 232, 208, 42, 191, 198, 252, 36, 213, 216, 192, 103, 249, 250, 228, 185, 39, 225, 71, - 23, 126, 234, 132, 191, 114, 234, 83, 173, 234, 149, 231, 146, 251, 93, 193, 56, 129, 199, - 235, 229, 118, 62, 221, 177, 96, 170, 205, 19, 182, 234, 188, 43, 148, 108, 142, 67, 144, - 63, 52, 239, 244, 67, 65, 127, 206, 102, 13, 227, 56, 201, 195, 246, 0, 155, 0, 46, 128, - 245, 6, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 85, 205, 14, 130, 48, 12, 238, 54, 20, 136, 222, + 124, 1, 19, 125, 128, 161, 241, 238, 187, 24, 111, 26, 61, 250, 248, 178, 216, 198, 89, 26, + 56, 216, 18, 248, 146, 165, 12, 218, 175, 255, 193, 193, 7, 85, 123, 28, 62, 23, 40, 61, + 202, 244, 62, 192, 47, 72, 247, 140, 50, 254, 135, 198, 233, 113, 69, 171, 24, 253, 12, 98, + 12, 6, 49, 66, 214, 255, 9, 246, 91, 179, 47, 170, 245, 11, 194, 254, 164, 221, 90, 180, + 103, 137, 247, 18, 101, 197, 11, 157, 140, 60, 116, 23, 47, 7, 13, 207, 10, 101, 45, 124, + 87, 76, 232, 88, 51, 191, 202, 252, 145, 138, 177, 133, 254, 124, 109, 243, 60, 68, 226, + 15, 38, 252, 177, 33, 254, 194, 168, 79, 37, 171, 87, 158, 75, 238, 119, 13, 223, 1, 188, + 60, 238, 207, 219, 245, 21, 4, 83, 110, 158, 176, 99, 247, 189, 80, 178, 33, 14, 66, 254, + 159, 233, 211, 119, 130, 254, 144, 205, 88, 163, 98, 180, 18, 167, 13, 116, 65, 190, 222, + 250, 76, 4, 233, 188, 7, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -392,11 +415,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, 82, 65, 10, 0, 32, 8, 211, 180, 255, 216, 15, 250, - 255, 171, 10, 82, 176, 232, 150, 30, 26, 200, 118, 144, 49, 135, 8, 11, 117, 14, 169, 102, - 229, 162, 140, 78, 219, 206, 137, 174, 44, 111, 104, 217, 190, 24, 236, 75, 113, 94, 146, - 93, 174, 252, 86, 46, 71, 223, 78, 46, 104, 129, 253, 155, 45, 60, 195, 5, 3, 89, 11, 161, - 73, 39, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 144, 75, 10, 0, 32, 8, 68, 253, 117, 31, 187, 65, + 247, 63, 85, 65, 10, 82, 203, 116, 209, 128, 60, 221, 12, 227, 32, 108, 181, 53, 108, 187, + 147, 140, 24, 118, 231, 169, 97, 212, 55, 245, 106, 95, 76, 246, 229, 60, 47, 173, 46, 87, + 127, 43, 87, 178, 127, 231, 16, 148, 194, 29, 195, 11, 220, 154, 119, 139, 115, 25, 38, 3, + 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -495,15 +518,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, 57, 17, 250, 99, 14, 250, - 224, 97, 144, 16, 146, 143, 231, 224, 45, 167, 126, 105, 217, 109, 118, 91, 248, 200, 168, - 225, 248, 63, 107, 114, 208, 233, 104, 188, 233, 139, 191, 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, 11, 22, 76, 132, 101, 231, 237, 229, 23, 189, 213, 54, 119, 15, 83, - 212, 199, 172, 175, 191, 226, 102, 96, 140, 251, 202, 84, 13, 204, 141, 224, 25, 176, 161, - 158, 53, 121, 144, 73, 14, 4, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 146, 81, 10, 195, 48, 8, 134, 77, 164, 247, 209, + 152, 52, 230, 109, 87, 89, 88, 122, 255, 35, 172, 99, 41, 11, 89, 161, 15, 77, 31, 250, + 193, 143, 34, 34, 250, 35, 194, 23, 172, 250, 48, 173, 50, 171, 44, 252, 48, 85, 176, 213, + 143, 154, 16, 58, 182, 198, 71, 141, 116, 14, 182, 205, 44, 161, 217, 251, 18, 93, 97, 225, + 39, 185, 148, 53, 144, 15, 121, 86, 86, 14, 26, 94, 78, 69, 138, 122, 141, 41, 167, 72, + 137, 189, 20, 94, 66, 146, 165, 14, 195, 113, 123, 17, 52, 38, 180, 185, 129, 127, 176, 51, + 240, 42, 175, 96, 160, 87, 118, 220, 94, 110, 170, 183, 218, 230, 238, 221, 39, 234, 191, + 172, 207, 177, 171, 153, 155, 153, 106, 96, 236, 3, 30, 249, 181, 199, 27, 99, 149, 130, + 253, 11, 4, 0, 0, ]; assert_eq!(bytes, expected_serialization); } diff --git a/acvm-repo/acvm/Cargo.toml b/acvm-repo/acvm/Cargo.toml index 2b143ebe475..722c825dca5 100644 --- a/acvm-repo/acvm/Cargo.toml +++ b/acvm-repo/acvm/Cargo.toml @@ -14,7 +14,6 @@ repository.workspace = true workspace = true [dependencies] -num-bigint.workspace = true thiserror.workspace = true tracing.workspace = true serde.workspace = true @@ -43,3 +42,5 @@ ark-bn254.workspace = true bn254_blackbox_solver.workspace = true proptest.workspace = true zkhash = { version = "^0.2.0", default-features = false } +num-bigint.workspace = true + diff --git a/acvm-repo/acvm/src/compiler/optimizers/constant_backpropagation.rs b/acvm-repo/acvm/src/compiler/optimizers/constant_backpropagation.rs index 5b778f63f07..994cfc84e66 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/constant_backpropagation.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/constant_backpropagation.rs @@ -3,14 +3,13 @@ use std::collections::{BTreeMap, BTreeSet, HashMap}; use crate::{ compiler::optimizers::GeneralOptimizer, pwg::{ - arithmetic::ExpressionSolver, blackbox::solve_range_opcode, directives::solve_directives, - BrilligSolver, BrilligSolverStatus, + arithmetic::ExpressionSolver, blackbox::solve_range_opcode, BrilligSolver, + BrilligSolverStatus, }, }; use acir::{ circuit::{ brillig::{Brillig, BrilligInputs, BrilligOutputs}, - directives::Directive, opcodes::BlackBoxFuncCall, Circuit, Opcode, }, @@ -212,34 +211,6 @@ impl ConstantBackpropagationOptimizer { } } - Opcode::Directive(Directive::ToLeRadix { a, b, radix }) => { - if b.iter().all(|output| known_witnesses.contains_key(output)) { - continue; - } else if b.iter().any(|witness| required_witnesses.contains(witness)) { - // If one of the brillig opcode's outputs is a required witness then we can't remove the opcode. In this case we can't replace - // all of the uses of this witness with the calculated constant so we'll be attempting to use an uninitialized witness. - // - // We then do not attempt execution of this opcode and just simplify the inputs. - Opcode::Directive(Directive::ToLeRadix { - a: remap_expression(&known_witnesses, a), - b, - radix, - }) - } else { - let directive = Directive::ToLeRadix { - a: remap_expression(&known_witnesses, a), - b, - radix, - }; - let result = solve_directives(&mut known_witnesses, &directive); - - match result { - Ok(()) => continue, - Err(_) => Opcode::Directive(directive), - } - } - } - Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { input }) => { if solve_range_opcode(&known_witnesses, &input).is_ok() { continue; @@ -288,7 +259,6 @@ mod tests { public_parameters: PublicInputs::default(), return_values: PublicInputs::default(), assert_messages: Default::default(), - recursive: false, } } diff --git a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs index e2585f64acd..9d0d5b3af60 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs @@ -3,7 +3,6 @@ use std::collections::{BTreeMap, BTreeSet, HashMap}; use acir::{ circuit::{ brillig::{BrilligInputs, BrilligOutputs}, - directives::Directive, opcodes::BlockId, Circuit, Opcode, }, @@ -161,7 +160,6 @@ impl MergeExpressionsOptimizer { witnesses } - Opcode::Directive(Directive::ToLeRadix { a, .. }) => CircuitSimulator::expr_wit(a), Opcode::MemoryOp { block_id: _, op, predicate } => { //index et value, et predicate let mut witnesses = CircuitSimulator::expr_wit(&op.index); @@ -297,7 +295,6 @@ mod tests { public_parameters: PublicInputs::default(), return_values: PublicInputs::default(), assert_messages: Default::default(), - recursive: false, }; check_circuit(circuit); } @@ -350,7 +347,6 @@ mod tests { public_parameters: PublicInputs::default(), return_values: PublicInputs::default(), assert_messages: Default::default(), - recursive: false, }; check_circuit(circuit); } diff --git a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs index 3570a36a7e7..f9c715a277f 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs @@ -191,7 +191,6 @@ mod tests { public_parameters: PublicInputs::default(), return_values: PublicInputs::default(), assert_messages: Default::default(), - recursive: false, } } diff --git a/acvm-repo/acvm/src/compiler/simulator.rs b/acvm-repo/acvm/src/compiler/simulator.rs index d89b53aa564..893195f342a 100644 --- a/acvm-repo/acvm/src/compiler/simulator.rs +++ b/acvm-repo/acvm/src/compiler/simulator.rs @@ -1,7 +1,6 @@ use acir::{ circuit::{ brillig::{BrilligInputs, BrilligOutputs}, - directives::Directive, opcodes::{BlockId, FunctionInput}, Circuit, Opcode, }, @@ -84,17 +83,6 @@ impl CircuitSimulator { } true } - Opcode::Directive(directive) => match directive { - Directive::ToLeRadix { a, b, .. } => { - if !self.can_solve_expression(a) { - return false; - } - for w in b { - self.mark_solvable(*w); - } - true - } - }, Opcode::MemoryOp { block_id, op, predicate } => { if !self.can_solve_expression(&op.index) { return false; @@ -246,7 +234,6 @@ mod tests { public_parameters, return_values: PublicInputs::default(), assert_messages: Default::default(), - recursive: false, } } diff --git a/acvm-repo/acvm/src/compiler/transformers/mod.rs b/acvm-repo/acvm/src/compiler/transformers/mod.rs index b11d054a57b..c9ce4ac7895 100644 --- a/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -1,5 +1,5 @@ use acir::{ - circuit::{brillig::BrilligOutputs, directives::Directive, Circuit, ExpressionWidth, Opcode}, + circuit::{brillig::BrilligOutputs, Circuit, ExpressionWidth, Opcode}, native_types::{Expression, Witness}, AcirField, }; @@ -104,17 +104,6 @@ pub(super) fn transform_internal( new_acir_opcode_positions.push(acir_opcode_positions[index]); transformed_opcodes.push(opcode); } - Opcode::Directive(ref directive) => { - match directive { - Directive::ToLeRadix { b, .. } => { - for witness in b { - transformer.mark_solvable(*witness); - } - } - } - new_acir_opcode_positions.push(acir_opcode_positions[index]); - transformed_opcodes.push(opcode); - } Opcode::MemoryInit { .. } => { // `MemoryInit` does not write values to the `WitnessMap` new_acir_opcode_positions.push(acir_opcode_positions[index]); diff --git a/acvm-repo/acvm/src/pwg/brillig.rs b/acvm-repo/acvm/src/pwg/brillig.rs index dffa45dbd7a..a5f5783478e 100644 --- a/acvm-repo/acvm/src/pwg/brillig.rs +++ b/acvm-repo/acvm/src/pwg/brillig.rs @@ -6,7 +6,6 @@ use acir::{ brillig::{BrilligFunctionId, BrilligInputs, BrilligOutputs}, opcodes::BlockId, ErrorSelector, OpcodeLocation, RawAssertionPayload, ResolvedAssertionPayload, - STRING_ERROR_SELECTOR, }, native_types::WitnessMap, AcirField, @@ -307,25 +306,10 @@ fn extract_failure_payload_from_memory( .expect("Error selector is not u64"), ); - match error_selector { - STRING_ERROR_SELECTOR => { - // If the error selector is 0, it means the error is a string - let string = revert_values_iter - .map(|&memory_value| { - let as_u8: u8 = memory_value.try_into().expect("String item is not u8"); - as_u8 as char - }) - .collect(); - Some(ResolvedAssertionPayload::String(string)) - } - _ => { - // If the error selector is not 0, it means the error is a custom error - Some(ResolvedAssertionPayload::Raw(RawAssertionPayload { - selector: error_selector, - data: revert_values_iter.map(|value| value.to_field()).collect(), - })) - } - } + Some(ResolvedAssertionPayload::Raw(RawAssertionPayload { + selector: error_selector, + data: revert_values_iter.map(|value| value.to_field()).collect(), + })) } } diff --git a/acvm-repo/acvm/src/pwg/directives/mod.rs b/acvm-repo/acvm/src/pwg/directives/mod.rs deleted file mode 100644 index d7bee88c278..00000000000 --- a/acvm-repo/acvm/src/pwg/directives/mod.rs +++ /dev/null @@ -1,49 +0,0 @@ -use acir::{circuit::directives::Directive, native_types::WitnessMap, AcirField}; -use num_bigint::BigUint; - -use crate::OpcodeResolutionError; - -use super::{get_value, insert_value, ErrorLocation}; - -/// Attempts to solve the [`Directive`] opcode `directive`. -/// If successful, `initial_witness` will be mutated to contain the new witness assignment. -/// -/// Returns `Ok(OpcodeResolution)` to signal whether the directive was successful solved. -/// -/// Returns `Err(OpcodeResolutionError)` if a circuit constraint is unsatisfied. -pub(crate) fn solve_directives( - initial_witness: &mut WitnessMap, - directive: &Directive, -) -> Result<(), OpcodeResolutionError> { - match directive { - Directive::ToLeRadix { a, b, radix } => { - let value_a = get_value(a, initial_witness)?; - let big_integer = BigUint::from_bytes_be(&value_a.to_be_bytes()); - - // Decompose the integer into its radix digits in little endian form. - let decomposed_integer = big_integer.to_radix_le(*radix); - - if b.len() < decomposed_integer.len() { - return Err(OpcodeResolutionError::UnsatisfiedConstrain { - opcode_location: ErrorLocation::Unresolved, - payload: None, - }); - } - - for (i, witness) in b.iter().enumerate() { - // Fetch the `i'th` digit from the decomposed integer list - // and convert it to a field element. - // If it is not available, which can happen when the decomposed integer - // list is shorter than the witness list, we return 0. - let value = match decomposed_integer.get(i) { - Some(digit) => F::from_be_bytes_reduce(&[*digit]), - None => F::zero(), - }; - - insert_value(witness, value, initial_witness)?; - } - - Ok(()) - } - } -} diff --git a/acvm-repo/acvm/src/pwg/mod.rs b/acvm-repo/acvm/src/pwg/mod.rs index fa3498da613..20c12a72fc0 100644 --- a/acvm-repo/acvm/src/pwg/mod.rs +++ b/acvm-repo/acvm/src/pwg/mod.rs @@ -10,7 +10,7 @@ use acir::{ AcirFunctionId, BlockId, ConstantOrWitnessEnum, FunctionInput, InvalidInputBitSize, }, AssertionPayload, ErrorSelector, ExpressionOrMemory, Opcode, OpcodeLocation, - RawAssertionPayload, ResolvedAssertionPayload, STRING_ERROR_SELECTOR, + RawAssertionPayload, ResolvedAssertionPayload, }, native_types::{Expression, Witness, WitnessMap}, AcirField, BlackBoxFunc, @@ -18,8 +18,7 @@ use acir::{ use acvm_blackbox_solver::BlackBoxResolutionError; use self::{ - arithmetic::ExpressionSolver, blackbox::bigint::AcvmBigIntSolver, directives::solve_directives, - memory_op::MemoryOpSolver, + arithmetic::ExpressionSolver, blackbox::bigint::AcvmBigIntSolver, memory_op::MemoryOpSolver, }; use crate::BlackBoxFunctionSolver; @@ -29,8 +28,6 @@ use thiserror::Error; pub(crate) mod arithmetic; // Brillig bytecode pub(crate) mod brillig; -// Directives -pub(crate) mod directives; // black box functions pub(crate) mod blackbox; mod memory_op; @@ -371,7 +368,6 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { bb_func, &mut self.bigint_solver, ), - Opcode::Directive(directive) => solve_directives(&mut self.witness_map, directive), Opcode::MemoryInit { block_id, init, .. } => { let solver = self.block_solvers.entry(*block_id).or_default(); solver.init(init, &self.witness_map) @@ -445,59 +441,32 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { &self, location: OpcodeLocation, ) -> Option> { - let (_, found_assertion_payload) = + let (_, assertion_descriptor) = self.assertion_payloads.iter().find(|(loc, _)| location == *loc)?; - match found_assertion_payload { - AssertionPayload::StaticString(string) => { - Some(ResolvedAssertionPayload::String(string.clone())) - } - AssertionPayload::Dynamic(error_selector, expression) => { - let mut fields = vec![]; - for expr in expression { - match expr { - ExpressionOrMemory::Expression(expr) => { - let value = get_value(expr, &self.witness_map).ok()?; - fields.push(value); - } - ExpressionOrMemory::Memory(block_id) => { - let memory_block = self.block_solvers.get(block_id)?; - fields.extend((0..memory_block.block_len).map(|memory_index| { - *memory_block - .block_value - .get(&memory_index) - .expect("All memory is initialized on creation") - })); - } - } + let mut fields = Vec::new(); + for expr in assertion_descriptor.payload.iter() { + match expr { + ExpressionOrMemory::Expression(expr) => { + let value = get_value(expr, &self.witness_map).ok()?; + fields.push(value); + } + ExpressionOrMemory::Memory(block_id) => { + let memory_block = self.block_solvers.get(block_id)?; + fields.extend((0..memory_block.block_len).map(|memory_index| { + *memory_block + .block_value + .get(&memory_index) + .expect("All memory is initialized on creation") + })); } - let error_selector = ErrorSelector::new(*error_selector); - - Some(match error_selector { - STRING_ERROR_SELECTOR => { - // If the error selector is 0, it means the error is a string - let string = fields - .iter() - .map(|field| { - let as_u8: u8 = field - .try_to_u64() - .expect("String character doesn't fit in u64") - .try_into() - .expect("String character doesn't fit in u8"); - as_u8 as char - }) - .collect(); - ResolvedAssertionPayload::String(string) - } - _ => { - // If the error selector is not 0, it means the error is a custom error - ResolvedAssertionPayload::Raw(RawAssertionPayload { - selector: error_selector, - data: fields, - }) - } - }) } } + let error_selector = ErrorSelector::new(assertion_descriptor.error_selector); + + Some(ResolvedAssertionPayload::Raw(RawAssertionPayload { + selector: error_selector, + data: fields, + })) } fn solve_brillig_call_opcode( @@ -530,7 +499,7 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { )?, }; - let result = solver.solve().map_err(|err| self.map_brillig_error(err))?; + let result = solver.solve()?; match result { BrilligSolverStatus::ForeignCallWait(foreign_call) => { @@ -570,31 +539,6 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { } } - fn map_brillig_error(&self, mut err: OpcodeResolutionError) -> OpcodeResolutionError { - match &mut err { - OpcodeResolutionError::BrilligFunctionFailed { call_stack, payload, .. } => { - // Some brillig errors have static strings as payloads, we can resolve them here - let last_location = - call_stack.last().expect("Call stacks should have at least one item"); - let assertion_descriptor = - self.assertion_payloads.iter().find_map(|(loc, payload)| { - if loc == last_location { - Some(payload) - } else { - None - } - }); - - if let Some(AssertionPayload::StaticString(string)) = assertion_descriptor { - *payload = Some(ResolvedAssertionPayload::String(string.clone())); - } - - err - } - _ => err, - } - } - pub fn step_into_brillig(&mut self) -> StepResult<'a, F, B> { let Opcode::BrilligCall { id, inputs, outputs, predicate } = &self.opcodes[self.instruction_pointer] diff --git a/acvm-repo/acvm/tests/solver.rs b/acvm-repo/acvm/tests/solver.rs index 2828ea3d79e..8b164b7c0f2 100644 --- a/acvm-repo/acvm/tests/solver.rs +++ b/acvm-repo/acvm/tests/solver.rs @@ -77,13 +77,6 @@ fn inversion_brillig_oracle_equivalence() { let w_x_plus_y = Witness(6); let w_equal_res = Witness(7); - let equal_opcode = BrilligOpcode::BinaryFieldOp { - op: BinaryFieldOp::Equals, - lhs: MemoryAddress::direct(0), - rhs: MemoryAddress::direct(1), - destination: MemoryAddress::direct(2), - }; - let opcodes = vec![ Opcode::BrilligCall { id: BrilligFunctionId(0), @@ -122,22 +115,38 @@ fn inversion_brillig_oracle_equivalence() { }), ]; + let equal_opcode = BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Equals, + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(1), + destination: MemoryAddress::direct(2), + }; + + let zero_usize = MemoryAddress::direct(3); + let two_usize = MemoryAddress::direct(4); + let three_usize = MemoryAddress::direct(5); + let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::Const { - destination: MemoryAddress::direct(0), + destination: zero_usize, + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + BrilligOpcode::Const { + destination: two_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(2u64), }, BrilligOpcode::Const { - destination: MemoryAddress::direct(1), + destination: three_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(0u64), + value: FieldElement::from(3u64), }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + size_address: two_usize, + offset_address: zero_usize, }, equal_opcode, // Oracles are named 'foreign calls' in brillig @@ -148,7 +157,9 @@ fn inversion_brillig_oracle_equivalence() { inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(0))], input_value_types: vec![HeapValueType::field()], }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 3 }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: three_usize }, + }, ], }; @@ -216,13 +227,6 @@ fn double_inversion_brillig_oracle() { let w_ij_oracle = Witness(10); let w_i_plus_j = Witness(11); - let equal_opcode = BrilligOpcode::BinaryFieldOp { - op: BinaryFieldOp::Equals, - lhs: MemoryAddress::direct(0), - rhs: MemoryAddress::direct(1), - destination: MemoryAddress::direct(4), - }; - let opcodes = vec![ Opcode::BrilligCall { id: BrilligFunctionId(0), @@ -268,22 +272,38 @@ fn double_inversion_brillig_oracle() { }), ]; + let zero_usize = MemoryAddress::direct(5); + let three_usize = MemoryAddress::direct(6); + let five_usize = MemoryAddress::direct(7); + + let equal_opcode = BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Equals, + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(1), + destination: MemoryAddress::direct(4), + }; + let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::Const { - destination: MemoryAddress::direct(0), + destination: zero_usize, + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + BrilligOpcode::Const { + destination: three_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(3u64), }, BrilligOpcode::Const { - destination: MemoryAddress::direct(1), + destination: five_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(0u64), + value: FieldElement::from(5u64), }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + size_address: three_usize, + offset_address: zero_usize, }, equal_opcode, // Oracles are named 'foreign calls' in brillig @@ -301,7 +321,9 @@ fn double_inversion_brillig_oracle() { inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(2))], input_value_types: vec![HeapValueType::field()], }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 5 }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: five_usize }, + }, ], }; @@ -386,22 +408,31 @@ fn oracle_dependent_execution() { let w_x_inv = Witness(3); let w_y_inv = Witness(4); + let zero_usize = MemoryAddress::direct(4); + let three_usize = MemoryAddress::direct(5); + let four_usize = MemoryAddress::direct(6); + let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::Const { - destination: MemoryAddress::direct(0), + destination: zero_usize, + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + BrilligOpcode::Const { + destination: three_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(3u64), }, BrilligOpcode::Const { - destination: MemoryAddress::direct(1), + destination: four_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(0u64), + value: FieldElement::from(4u64), }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + size_address: three_usize, + offset_address: zero_usize, }, // Oracles are named 'foreign calls' in brillig BrilligOpcode::ForeignCall { function: "invert".into(), @@ -417,7 +448,9 @@ fn oracle_dependent_execution() { inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(2))], input_value_types: vec![HeapValueType::field()], }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 4 }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: four_usize }, + }, ], }; @@ -662,7 +695,7 @@ fn unsatisfied_opcode_resolved_brillig() { }; // Jump pass the trap if the values are equal, else // jump to the trap - let location_of_stop = 3; + let location_of_stop = 7; let jmp_if_opcode = BrilligOpcode::JumpIf { condition: MemoryAddress::direct(2), location: location_of_stop }; @@ -673,7 +706,12 @@ fn unsatisfied_opcode_resolved_brillig() { size: MemoryAddress::direct(3), }, }; - let stop_opcode = BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }; + let stop_opcode = BrilligOpcode::Stop { + return_data: HeapVector { + pointer: MemoryAddress::direct(0), + size: MemoryAddress::direct(3), + }, + }; let brillig_bytecode = BrilligBytecode { bytecode: vec![ diff --git a/acvm-repo/acvm_js/test/shared/addition.ts b/acvm-repo/acvm_js/test/shared/addition.ts index 820a415acf3..2b8124e77d7 100644 --- a/acvm-repo/acvm_js/test/shared/addition.ts +++ b/acvm-repo/acvm_js/test/shared/addition.ts @@ -3,10 +3,10 @@ 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, 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, + 255, 9, 106, 228, 64, 194, 81, 38, 105, 182, 167, 201, 102, 189, 251, 216, 159, 243, 110, 38, 244, 60, 122, 194, 63, + 208, 47, 116, 109, 131, 139, 32, 49, 215, 28, 43, 18, 158, 16, 173, 168, 0, 75, 73, 138, 138, 162, 114, 69, 37, 170, + 202, 154, 173, 88, 6, 67, 166, 138, 77, 140, 90, 151, 133, 117, 189, 224, 117, 108, 221, 229, 135, 223, 13, 27, 135, + 121, 106, 119, 3, 58, 173, 124, 163, 140, 1, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ diff --git a/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts b/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts index 8eb7b7d5059..24fbc1a921a 100644 --- a/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts +++ b/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts @@ -2,14 +2,14 @@ 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, 85, 93, 10, 194, 48, 12, 78, 155, 233, 54, 240, 205, 11, 8, 122, 128, 76, 47, - 176, 187, 136, 111, 138, 62, 122, 124, 45, 75, 88, 23, 139, 19, 76, 64, 63, 24, 89, 75, 242, 229, 159, 6, 24, 208, 60, - 191, 192, 255, 11, 150, 145, 101, 186, 71, 152, 66, 116, 123, 150, 244, 29, 186, 96, 199, 69, 94, 49, 198, 63, 136, - 17, 29, 98, 132, 172, 255, 63, 216, 111, 203, 190, 152, 214, 15, 11, 251, 83, 193, 176, 95, 75, 62, 215, 44, 27, 93, - 232, 100, 20, 225, 117, 241, 38, 144, 233, 105, 149, 4, 229, 185, 183, 201, 232, 208, 42, 191, 198, 252, 36, 213, 216, - 192, 103, 249, 250, 228, 185, 39, 225, 71, 23, 126, 234, 132, 191, 114, 234, 83, 173, 234, 149, 231, 146, 251, 93, - 193, 56, 129, 199, 235, 229, 118, 62, 221, 177, 96, 170, 205, 19, 182, 234, 188, 43, 148, 108, 142, 67, 144, 63, 52, - 239, 244, 67, 65, 127, 206, 102, 13, 227, 56, 201, 195, 246, 0, 155, 0, 46, 128, 245, 6, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 85, 205, 14, 130, 48, 12, 238, 54, 20, 136, 222, 124, 1, 19, 125, 128, 161, + 241, 238, 187, 24, 111, 26, 61, 250, 248, 178, 216, 198, 89, 26, 56, 216, 18, 248, 146, 165, 12, 218, 175, 255, 193, + 193, 7, 85, 123, 28, 62, 23, 40, 61, 202, 244, 62, 192, 47, 72, 247, 140, 50, 254, 135, 198, 233, 113, 69, 171, 24, + 253, 12, 98, 12, 6, 49, 66, 214, 255, 9, 246, 91, 179, 47, 170, 245, 11, 194, 254, 164, 221, 90, 180, 103, 137, 247, + 18, 101, 197, 11, 157, 140, 60, 116, 23, 47, 7, 13, 207, 10, 101, 45, 124, 87, 76, 232, 88, 51, 191, 202, 252, 145, + 138, 177, 133, 254, 124, 109, 243, 60, 68, 226, 15, 38, 252, 177, 33, 254, 194, 168, 79, 37, 171, 87, 158, 75, 238, + 119, 13, 223, 1, 188, 60, 238, 207, 219, 245, 21, 4, 83, 110, 158, 176, 99, 247, 189, 80, 178, 33, 14, 66, 254, 159, + 233, 211, 119, 130, 254, 144, 205, 88, 163, 98, 180, 18, 167, 13, 116, 65, 190, 222, 250, 76, 4, 233, 188, 7, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/acvm-repo/acvm_js/test/shared/foreign_call.ts b/acvm-repo/acvm_js/test/shared/foreign_call.ts index dc3c6f23f6f..da0b9974c61 100644 --- a/acvm-repo/acvm_js/test/shared/foreign_call.ts +++ b/acvm-repo/acvm_js/test/shared/foreign_call.ts @@ -2,11 +2,11 @@ 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, 79, 73, 10, 128, 48, 12, 204, 40, 46, 5, 111, 126, 36, 254, 192, 207, 120, - 240, 226, 65, 196, 247, 91, 48, 129, 80, 218, 122, 48, 3, 33, 147, 9, 89, 6, 244, 98, 140, 1, 225, 157, 100, 173, 45, - 84, 91, 37, 243, 63, 44, 240, 219, 197, 246, 223, 38, 37, 176, 34, 85, 156, 169, 251, 144, 233, 183, 142, 206, 67, - 114, 215, 121, 63, 15, 84, 135, 222, 157, 98, 244, 194, 247, 227, 222, 206, 11, 31, 19, 165, 186, 164, 207, 153, 222, - 3, 91, 101, 84, 220, 120, 2, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 81, 203, 10, 128, 48, 12, 179, 243, 57, 240, 230, 143, 108, 127, 224, 207, + 120, 240, 226, 65, 196, 239, 119, 98, 11, 101, 100, 94, 214, 64, 73, 26, 88, 73, 24, 53, 31, 166, 52, 196, 186, 99, + 150, 93, 67, 188, 149, 57, 212, 33, 146, 221, 173, 160, 243, 186, 92, 144, 54, 127, 138, 245, 204, 62, 243, 95, 110, + 13, 195, 122, 144, 207, 240, 126, 28, 65, 71, 7, 250, 206, 105, 6, 214, 251, 113, 111, 231, 133, 190, 93, 191, 40, + 237, 37, 127, 1, 190, 36, 121, 0, 128, 254, 118, 42, 127, 2, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000005'], diff --git a/acvm-repo/acvm_js/test/shared/memory_op.ts b/acvm-repo/acvm_js/test/shared/memory_op.ts index f7443c2258b..2f0fbfb85f1 100644 --- a/acvm-repo/acvm_js/test/shared/memory_op.ts +++ b/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, 82, 65, 10, 0, 32, 8, 211, 180, 255, 216, 15, 250, 255, 171, 10, 82, 176, 232, - 150, 30, 26, 200, 118, 144, 49, 135, 8, 11, 117, 14, 169, 102, 229, 162, 140, 78, 219, 206, 137, 174, 44, 111, 104, - 217, 190, 24, 236, 75, 113, 94, 146, 93, 174, 252, 86, 46, 71, 223, 78, 46, 104, 129, 253, 155, 45, 60, 195, 5, 3, 89, - 11, 161, 73, 39, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 144, 75, 10, 0, 32, 8, 68, 253, 117, 31, 187, 65, 247, 63, 85, 65, 10, 82, + 203, 116, 209, 128, 60, 221, 12, 227, 32, 108, 181, 53, 108, 187, 147, 140, 24, 118, 231, 169, 97, 212, 55, 245, 106, + 95, 76, 246, 229, 60, 47, 173, 46, 87, 127, 43, 87, 178, 127, 231, 16, 148, 194, 29, 195, 11, 220, 154, 119, 139, 115, + 25, 38, 3, 0, 0, ]); export const initialWitnessMap = new Map([ diff --git a/acvm-repo/acvm_js/test/shared/multi_scalar_mul.ts b/acvm-repo/acvm_js/test/shared/multi_scalar_mul.ts index 239d5473606..3ec589dd0c8 100644 --- a/acvm-repo/acvm_js/test/shared/multi_scalar_mul.ts +++ b/acvm-repo/acvm_js/test/shared/multi_scalar_mul.ts @@ -1,8 +1,8 @@ // See `multi_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, 93, 77, 9, 14, 0, 32, 8, 202, 171, 227, 255, 255, 109, 217, 162, 141, 114, 99, 2, - 162, 74, 57, 53, 18, 2, 46, 208, 70, 122, 99, 162, 43, 113, 35, 239, 102, 157, 230, 1, 94, 19, 45, 209, 145, 11, 202, - 43, 238, 56, 249, 133, 254, 255, 187, 79, 45, 204, 84, 220, 246, 193, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 77, 9, 10, 0, 32, 8, 243, 236, 248, 255, 127, 35, 163, 5, 35, 97, 184, 205, + 169, 42, 183, 102, 65, 193, 21, 218, 73, 31, 44, 116, 35, 238, 228, 189, 108, 208, 60, 193, 91, 161, 23, 6, 114, 73, + 121, 195, 157, 32, 95, 232, 255, 191, 203, 181, 1, 243, 231, 24, 106, 192, 0, 0, 0, ]); export const initialWitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/acvm-repo/acvm_js/test/shared/nested_acir_call.ts b/acvm-repo/acvm_js/test/shared/nested_acir_call.ts index 64051dff93f..3464809dfc4 100644 --- a/acvm-repo/acvm_js/test/shared/nested_acir_call.ts +++ b/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, 57, 17, 250, 99, 14, 250, 224, 97, 144, 16, 146, 143, 231, 224, 45, 167, 126, 105, - 217, 109, 118, 91, 248, 200, 168, 225, 248, 63, 107, 114, 208, 233, 104, 188, 233, 139, 191, 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, 11, 22, 76, 132, 101, - 231, 237, 229, 23, 189, 213, 54, 119, 15, 83, 212, 199, 172, 175, 191, 226, 102, 96, 140, 251, 202, 84, 13, 204, 141, - 224, 25, 176, 161, 158, 53, 121, 144, 73, 14, 4, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 146, 81, 10, 195, 48, 8, 134, 77, 164, 247, 209, 152, 52, 230, 109, 87, 89, + 88, 122, 255, 35, 172, 99, 41, 11, 89, 161, 15, 77, 31, 250, 193, 143, 34, 34, 250, 35, 194, 23, 172, 250, 48, 173, + 50, 171, 44, 252, 48, 85, 176, 213, 143, 154, 16, 58, 182, 198, 71, 141, 116, 14, 182, 205, 44, 161, 217, 251, 18, 93, + 97, 225, 39, 185, 148, 53, 144, 15, 121, 86, 86, 14, 26, 94, 78, 69, 138, 122, 141, 41, 167, 72, 137, 189, 20, 94, 66, + 146, 165, 14, 195, 113, 123, 17, 52, 38, 180, 185, 129, 127, 176, 51, 240, 42, 175, 96, 160, 87, 118, 220, 94, 110, + 170, 183, 218, 230, 238, 221, 39, 234, 191, 172, 207, 177, 171, 153, 155, 153, 106, 96, 236, 3, 30, 249, 181, 199, 27, + 99, 149, 130, 253, 11, 4, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ diff --git a/acvm-repo/acvm_js/test/shared/schnorr_verify.ts b/acvm-repo/acvm_js/test/shared/schnorr_verify.ts index 830ca1026d6..d2df63a8ddb 100644 --- a/acvm-repo/acvm_js/test/shared/schnorr_verify.ts +++ b/acvm-repo/acvm_js/test/shared/schnorr_verify.ts @@ -1,19 +1,19 @@ // 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, 85, 211, 103, 78, 2, 81, 24, 70, 225, 193, 130, 96, 239, 189, 96, 239, 189, 35, 34, - 34, 34, 34, 238, 130, 253, 47, 129, 192, 9, 223, 36, 7, 146, 201, 60, 209, 31, 144, 123, 207, 155, 73, 250, 159, 118, - 239, 201, 132, 121, 103, 227, 205, 211, 137, 247, 144, 60, 220, 123, 114, 225, 17, 121, 84, 206, 202, 99, 114, 78, - 206, 203, 227, 242, 132, 60, 41, 79, 201, 211, 242, 140, 60, 43, 207, 201, 243, 242, 130, 188, 40, 47, 201, 203, 242, - 138, 188, 42, 175, 201, 235, 242, 134, 188, 41, 111, 201, 219, 242, 142, 92, 144, 119, 229, 61, 121, 95, 62, 144, 15, - 229, 35, 249, 88, 62, 145, 79, 229, 51, 249, 92, 190, 144, 47, 229, 43, 249, 90, 190, 145, 111, 229, 59, 249, 94, 126, - 144, 31, 229, 39, 249, 89, 126, 145, 95, 229, 162, 252, 38, 151, 228, 119, 185, 44, 127, 200, 21, 249, 83, 174, 134, - 233, 52, 137, 191, 125, 233, 255, 53, 249, 91, 174, 203, 63, 114, 67, 254, 149, 155, 242, 159, 220, 10, 255, 199, 247, - 183, 244, 59, 216, 38, 155, 100, 139, 108, 144, 237, 165, 155, 203, 199, 111, 102, 83, 108, 137, 13, 177, 29, 54, 195, - 86, 216, 8, 219, 96, 19, 108, 129, 13, 208, 62, 205, 211, 58, 141, 211, 54, 77, 211, 50, 13, 211, 46, 205, 22, 146, - 126, 163, 180, 73, 147, 180, 72, 131, 180, 71, 115, 180, 70, 99, 180, 69, 83, 180, 68, 67, 180, 67, 51, 180, 66, 35, - 180, 65, 19, 180, 64, 3, 220, 61, 119, 206, 93, 115, 199, 197, 184, 211, 82, 220, 97, 57, 238, 172, 18, 119, 84, 141, - 187, 168, 197, 217, 215, 227, 172, 27, 113, 182, 205, 56, 203, 244, 204, 210, 115, 75, 116, 158, 3, 159, 46, 43, 32, - 188, 53, 25, 5, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 211, 103, 78, 2, 81, 24, 70, 225, 193, 130, 96, 239, 189, 96, 239, 189, 35, 34, + 34, 34, 82, 118, 193, 254, 151, 64, 224, 132, 111, 146, 67, 50, 153, 39, 250, 3, 114, 239, 121, 51, 201, 240, 211, 29, + 60, 153, 48, 239, 108, 188, 121, 122, 241, 30, 145, 71, 7, 79, 46, 60, 38, 143, 203, 89, 121, 66, 206, 201, 121, 121, + 82, 158, 146, 167, 229, 25, 121, 86, 158, 147, 231, 229, 5, 121, 81, 94, 146, 151, 229, 21, 121, 85, 94, 147, 215, + 229, 13, 121, 83, 222, 146, 183, 229, 29, 121, 87, 222, 147, 11, 242, 190, 124, 32, 31, 202, 71, 242, 177, 124, 34, + 159, 202, 103, 242, 185, 124, 33, 95, 202, 87, 242, 181, 124, 35, 223, 202, 119, 242, 189, 252, 32, 63, 202, 79, 242, + 179, 252, 34, 191, 202, 111, 242, 187, 92, 148, 63, 228, 146, 252, 41, 151, 229, 47, 185, 34, 127, 203, 213, 48, 157, + 38, 241, 183, 31, 253, 191, 38, 255, 202, 117, 249, 79, 110, 200, 255, 114, 83, 110, 201, 237, 112, 39, 190, 191, 173, + 223, 193, 54, 217, 36, 91, 100, 131, 108, 47, 221, 92, 62, 126, 51, 155, 98, 75, 108, 136, 237, 176, 25, 182, 194, 70, + 216, 6, 155, 96, 11, 108, 128, 246, 105, 158, 214, 105, 156, 182, 105, 154, 150, 105, 152, 118, 105, 182, 144, 12, 27, + 165, 77, 154, 164, 69, 26, 164, 61, 154, 163, 53, 26, 163, 45, 154, 162, 37, 26, 162, 29, 154, 161, 21, 26, 161, 13, + 154, 160, 5, 26, 224, 238, 185, 115, 238, 154, 59, 46, 198, 157, 150, 226, 14, 203, 113, 103, 149, 184, 163, 106, 220, + 69, 45, 206, 190, 30, 103, 221, 136, 179, 109, 198, 89, 166, 103, 150, 158, 91, 162, 243, 244, 167, 15, 14, 161, 226, + 6, 24, 5, 0, 0, ]); export const initialWitnessMap = new Map([ diff --git a/acvm-repo/brillig/src/lib.rs b/acvm-repo/brillig/src/lib.rs index 5bd9f898d59..cf31ff79996 100644 --- a/acvm-repo/brillig/src/lib.rs +++ b/acvm-repo/brillig/src/lib.rs @@ -4,7 +4,6 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] //! The Brillig bytecode is distinct from regular [ACIR][acir] in that it does not generate constraints. -//! This is a generalization over the fixed directives that exists within in the ACVM. //! //! [acir]: https://crates.io/crates/acir //! [acvm]: https://crates.io/crates/acvm diff --git a/acvm-repo/brillig/src/opcodes.rs b/acvm-repo/brillig/src/opcodes.rs index 0d87c5b9410..8b72b5a9b41 100644 --- a/acvm-repo/brillig/src/opcodes.rs +++ b/acvm-repo/brillig/src/opcodes.rs @@ -309,8 +309,7 @@ pub enum BrilligOpcode { }, /// Stop execution, returning data after the offset Stop { - return_data_offset: usize, - return_data_size: usize, + return_data: HeapVector, }, } diff --git a/acvm-repo/brillig_vm/src/lib.rs b/acvm-repo/brillig_vm/src/lib.rs index 89d72c4614b..45025fbb208 100644 --- a/acvm-repo/brillig_vm/src/lib.rs +++ b/acvm-repo/brillig_vm/src/lib.rs @@ -6,7 +6,6 @@ //! The Brillig VM is a specialized VM which allows the [ACVM][acvm] to perform custom non-determinism. //! //! Brillig bytecode is distinct from regular [ACIR][acir] in that it does not generate constraints. -//! This is a generalization over the fixed directives that exists within in the ACVM. //! //! [acir]: https://crates.io/crates/acir //! [acvm]: https://crates.io/crates/acvm @@ -357,8 +356,16 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { self.trap(0, 0) } } - Opcode::Stop { return_data_offset, return_data_size } => { - self.finish(*return_data_offset, *return_data_size) + Opcode::Stop { return_data } => { + let return_data_size = self.memory.read(return_data.size).to_usize(); + if return_data_size > 0 { + self.finish( + self.memory.read_ref(return_data.pointer).unwrap_direct(), + return_data_size, + ) + } else { + self.finish(0, 0) + } } Opcode::Load { destination: destination_address, source_pointer } => { // Convert our source_pointer to an address @@ -1005,28 +1012,37 @@ mod tests { fn cast_opcode() { let calldata: Vec = vec![((2_u128.pow(32)) - 1).into()]; + let value_address = MemoryAddress::direct(1); + let one_usize = MemoryAddress::direct(2); + let zero_usize = MemoryAddress::direct(3); + let opcodes = &[ Opcode::Const { - destination: MemoryAddress::direct(0), + destination: one_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(1u64), }, Opcode::Const { - destination: MemoryAddress::direct(1), + destination: zero_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, Opcode::CalldataCopy { - destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + destination_address: value_address, + size_address: one_usize, + offset_address: zero_usize, }, Opcode::Cast { - destination: MemoryAddress::direct(1), - source: MemoryAddress::direct(0), + destination: value_address, + source: value_address, bit_size: BitSize::Integer(IntegerBitSize::U8), }, - Opcode::Stop { return_data_offset: 1, return_data_size: 1 }, + Opcode::Stop { + return_data: HeapVector { + pointer: one_usize, // Since value_address is direct(1) + size: one_usize, + }, + }, ]; let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver, false); @@ -1051,33 +1067,42 @@ mod tests { fn not_opcode() { let calldata: Vec = vec![(1_usize).into()]; + let value_address = MemoryAddress::direct(1); + let one_usize = MemoryAddress::direct(2); + let zero_usize = MemoryAddress::direct(3); + let opcodes = &[ Opcode::Const { - destination: MemoryAddress::direct(0), + destination: one_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(1u64), }, Opcode::Const { - destination: MemoryAddress::direct(1), + destination: zero_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, Opcode::CalldataCopy { - destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + destination_address: value_address, + size_address: one_usize, + offset_address: zero_usize, }, Opcode::Cast { - destination: MemoryAddress::direct(1), - source: MemoryAddress::direct(0), + destination: value_address, + source: value_address, bit_size: BitSize::Integer(IntegerBitSize::U128), }, Opcode::Not { - destination: MemoryAddress::direct(1), - source: MemoryAddress::direct(1), + destination: value_address, + source: value_address, bit_size: IntegerBitSize::U128, }, - Opcode::Stop { return_data_offset: 1, return_data_size: 1 }, + Opcode::Stop { + return_data: HeapVector { + pointer: one_usize, // Since value_address is direct(1) + size: one_usize, + }, + }, ]; let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver, false); diff --git a/compiler/integration-tests/package.json b/compiler/integration-tests/package.json index a438c2965c3..a9d437da792 100644 --- a/compiler/integration-tests/package.json +++ b/compiler/integration-tests/package.json @@ -13,7 +13,7 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "0.61.0", + "@aztec/bb.js": "0.63.1", "@noir-lang/noir_js": "workspace:*", "@noir-lang/noir_wasm": "workspace:*", "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", diff --git a/compiler/integration-tests/scripts/codegen-verifiers.sh b/compiler/integration-tests/scripts/codegen-verifiers.sh index bec59eb6889..de1f71a4cc0 100755 --- a/compiler/integration-tests/scripts/codegen-verifiers.sh +++ b/compiler/integration-tests/scripts/codegen-verifiers.sh @@ -17,8 +17,8 @@ KEYS=$(mktemp -d) # Codegen verifier contract for 1_mul mul_dir=$repo_root/test_programs/execution_success/1_mul nargo --program-dir $mul_dir compile -$NARGO_BACKEND_PATH write_vk -b $mul_dir/target/1_mul.json -o $KEYS/1_mul -$NARGO_BACKEND_PATH contract -k $KEYS/1_mul -o $contracts_dir/1_mul.sol +$NARGO_BACKEND_PATH write_vk -b $mul_dir/target/1_mul.json -o $KEYS/1_mul +$NARGO_BACKEND_PATH contract -k $KEYS/1_mul -o $contracts_dir/1_mul.sol # Codegen verifier contract for assert_statement assert_statement_dir=$repo_root/test_programs/execution_success/assert_statement diff --git a/compiler/integration-tests/test/browser/recursion.test.ts b/compiler/integration-tests/test/browser/recursion.test.ts index 4ee92d5b795..71d6697f843 100644 --- a/compiler/integration-tests/test/browser/recursion.test.ts +++ b/compiler/integration-tests/test/browser/recursion.test.ts @@ -19,7 +19,7 @@ await newABICoder(); await initACVM(); const base_relative_path = '../../../../..'; -const circuit_main = 'test_programs/execution_success/assert_statement_recursive'; +const circuit_main = 'test_programs/execution_success/assert_statement'; const circuit_recursion = 'compiler/integration-tests/circuits/recursion'; async function getCircuit(projectPath: string) { @@ -45,7 +45,7 @@ describe('It compiles noir program code, receiving circuit bytes and abi object. const main_program = await getCircuit(`${base_relative_path}/${circuit_main}`); const main_inputs: InputMap = TOML.parse(circuit_main_toml) as InputMap; - const main_backend = new UltraPlonkBackend(main_program.bytecode); + const main_backend = new UltraPlonkBackend(main_program.bytecode, {}, { recursive: true }); const { witness: main_witnessUint8Array } = await new Noir(main_program).execute(main_inputs); @@ -73,7 +73,7 @@ describe('It compiles noir program code, receiving circuit bytes and abi object. const recursion_program = await getCircuit(`${base_relative_path}/${circuit_recursion}`); - const recursion_backend = new UltraPlonkBackend(recursion_program.bytecode); + const recursion_backend = new UltraPlonkBackend(recursion_program.bytecode, {}, { recursive: false }); const { witness: recursion_witnessUint8Array } = await new Noir(recursion_program).execute(recursion_inputs); diff --git a/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts b/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts index b08d52e1604..1694da28805 100644 --- a/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts +++ b/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts @@ -17,7 +17,7 @@ it.skip(`smart contract can verify a recursive proof`, async () => { const fm = createFileManager(basePath); const innerCompilationResult = await compile( fm, - join(basePath, './test_programs/execution_success/assert_statement_recursive'), + join(basePath, './test_programs/execution_success/assert_statement'), ); if (!('program' in innerCompilationResult)) { throw new Error('Compilation failed'); @@ -35,11 +35,11 @@ it.skip(`smart contract can verify a recursive proof`, async () => { // Intermediate proof - const inner_backend = new UltraPlonkBackend(innerProgram.bytecode); + const inner_backend = new UltraPlonkBackend(innerProgram.bytecode, {}, { recursive: true }); const inner = new Noir(innerProgram); const inner_prover_toml = readFileSync( - join(basePath, `./test_programs/execution_success/assert_statement_recursive/Prover.toml`), + join(basePath, `./test_programs/execution_success/assert_statement/Prover.toml`), ).toString(); const inner_inputs = toml.parse(inner_prover_toml); @@ -67,7 +67,7 @@ it.skip(`smart contract can verify a recursive proof`, async () => { const { witness: recursionWitness } = await recursion.execute(recursion_inputs); - const recursion_backend = new UltraPlonkBackend(recursionProgram.bytecode); + const recursion_backend = new UltraPlonkBackend(recursionProgram.bytecode, {}, { recursive: false }); const recursion_proof = await recursion_backend.generateProof(recursionWitness); expect(await recursion_backend.verifyProof(recursion_proof)).to.be.true; diff --git a/compiler/integration-tests/test/node/smart_contract_verifier.test.ts b/compiler/integration-tests/test/node/smart_contract_verifier.test.ts index c43fba01424..74a36262829 100644 --- a/compiler/integration-tests/test/node/smart_contract_verifier.test.ts +++ b/compiler/integration-tests/test/node/smart_contract_verifier.test.ts @@ -46,7 +46,7 @@ test_cases.forEach((testInfo) => { const inputs = toml.parse(prover_toml); const { witness } = await program.execute(inputs); - const backend = new UltraPlonkBackend(noir_program.bytecode); + const backend = new UltraPlonkBackend(noir_program.bytecode, {}, { recursive: false }); const proofData = await backend.generateProof(witness); // JS verification diff --git a/compiler/noirc_driver/src/abi_gen.rs b/compiler/noirc_driver/src/abi_gen.rs index 4cd480b883d..625a35c8d15 100644 --- a/compiler/noirc_driver/src/abi_gen.rs +++ b/compiler/noirc_driver/src/abi_gen.rs @@ -7,6 +7,7 @@ use noirc_abi::{ Abi, AbiErrorType, AbiParameter, AbiReturnType, AbiType, AbiValue, AbiVisibility, Sign, }; use noirc_errors::Span; +use noirc_evaluator::ErrorType; use noirc_frontend::ast::{Signedness, Visibility}; use noirc_frontend::TypeBinding; use noirc_frontend::{ @@ -26,7 +27,7 @@ pub(super) fn gen_abi( context: &Context, func_id: &FuncId, return_visibility: Visibility, - error_types: BTreeMap, + error_types: BTreeMap, ) -> Abi { let (parameters, return_type) = compute_function_abi(context, func_id); let return_type = return_type.map(|typ| AbiReturnType { @@ -35,7 +36,7 @@ pub(super) fn gen_abi( }); let error_types = error_types .into_iter() - .map(|(selector, typ)| (selector, build_abi_error_type(context, &typ))) + .map(|(selector, typ)| (selector, build_abi_error_type(context, typ))) .collect(); Abi { parameters, return_type, error_types } } @@ -49,19 +50,23 @@ fn get_main_function_span(context: &Context) -> Span { } } -fn build_abi_error_type(context: &Context, typ: &Type) -> AbiErrorType { +fn build_abi_error_type(context: &Context, typ: ErrorType) -> AbiErrorType { match typ { - Type::FmtString(len, item_types) => { - let span = get_main_function_span(context); - let length = len.evaluate_to_u32(span).expect("Cannot evaluate fmt length"); - let Type::Tuple(item_types) = item_types.as_ref() else { - unreachable!("FmtString items must be a tuple") - }; - let item_types = - item_types.iter().map(|typ| abi_type_from_hir_type(context, typ)).collect(); - AbiErrorType::FmtString { length, item_types } + ErrorType::Dynamic(typ) => { + if let Type::FmtString(len, item_types) = typ { + let span = get_main_function_span(context); + let length = len.evaluate_to_u32(span).expect("Cannot evaluate fmt length"); + let Type::Tuple(item_types) = item_types.as_ref() else { + unreachable!("FmtString items must be a tuple") + }; + let item_types = + item_types.iter().map(|typ| abi_type_from_hir_type(context, typ)).collect(); + AbiErrorType::FmtString { length, item_types } + } else { + AbiErrorType::Custom(abi_type_from_hir_type(context, &typ)) + } } - _ => AbiErrorType::Custom(abi_type_from_hir_type(context, typ)), + ErrorType::String(string) => AbiErrorType::String { string }, } } diff --git a/compiler/noirc_evaluator/Cargo.toml b/compiler/noirc_evaluator/Cargo.toml index aac07339dd6..e25b5bf855a 100644 --- a/compiler/noirc_evaluator/Cargo.toml +++ b/compiler/noirc_evaluator/Cargo.toml @@ -20,7 +20,6 @@ fxhash.workspace = true iter-extended.workspace = true thiserror.workspace = true num-bigint = "0.4" -num-traits.workspace = true im.workspace = true serde.workspace = true serde_json.workspace = true @@ -33,6 +32,7 @@ cfg-if.workspace = true [dev-dependencies] proptest.workspace = true similar-asserts.workspace = true +num-traits.workspace = true [features] bn254 = ["noirc_frontend/bn254"] diff --git a/compiler/noirc_evaluator/src/acir/acir_variable.rs b/compiler/noirc_evaluator/src/acir/acir_variable.rs index 6aa8bc32975..6ba072f01a4 100644 --- a/compiler/noirc_evaluator/src/acir/acir_variable.rs +++ b/compiler/noirc_evaluator/src/acir/acir_variable.rs @@ -1112,10 +1112,10 @@ impl> AcirContext { let witness = self.var_to_witness(witness_var)?; self.acir_ir.range_constraint(witness, *bit_size)?; if let Some(message) = message { - self.acir_ir.assertion_payloads.insert( - self.acir_ir.last_acir_opcode_location(), - AssertionPayload::StaticString(message.clone()), - ); + let payload = self.generate_assertion_message_payload(message.clone()); + self.acir_ir + .assertion_payloads + .insert(self.acir_ir.last_acir_opcode_location(), payload); } } NumericType::NativeField => { @@ -2072,6 +2072,13 @@ impl> AcirContext { self.acir_ir.push_opcode(Opcode::Call { id, inputs, outputs, predicate }); Ok(results) } + + pub(crate) fn generate_assertion_message_payload( + &mut self, + message: String, + ) -> AssertionPayload { + self.acir_ir.generate_assertion_message_payload(message) + } } /// Enum representing the possible values that a diff --git a/compiler/noirc_evaluator/src/acir/brillig_directive.rs b/compiler/noirc_evaluator/src/acir/brillig_directive.rs index 49e259e0ce5..89fc7f1eda5 100644 --- a/compiler/noirc_evaluator/src/acir/brillig_directive.rs +++ b/compiler/noirc_evaluator/src/acir/brillig_directive.rs @@ -1,5 +1,8 @@ use acvm::acir::{ - brillig::{BinaryFieldOp, BitSize, IntegerBitSize, MemoryAddress, Opcode as BrilligOpcode}, + brillig::{ + BinaryFieldOp, BinaryIntOp, BitSize, HeapVector, IntegerBitSize, MemoryAddress, + Opcode as BrilligOpcode, + }, AcirField, }; @@ -18,25 +21,27 @@ pub(crate) fn directive_invert() -> GeneratedBrillig { let one_const = MemoryAddress::direct(1); let zero_const = MemoryAddress::direct(2); let input_is_zero = MemoryAddress::direct(3); + let zero_usize = MemoryAddress::direct(20); + let one_usize = MemoryAddress::direct(21); // Location of the stop opcode let stop_location = 8; GeneratedBrillig { byte_code: vec![ BrilligOpcode::Const { - destination: MemoryAddress::direct(20), + destination: one_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: F::from(1_usize), }, BrilligOpcode::Const { - destination: MemoryAddress::direct(21), + destination: zero_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: F::from(0_usize), }, BrilligOpcode::CalldataCopy { destination_address: input, - size_address: MemoryAddress::direct(20), - offset_address: MemoryAddress::direct(21), + size_address: one_usize, + offset_address: zero_usize, }, // Put value zero in register (2) BrilligOpcode::Const { @@ -65,7 +70,9 @@ pub(crate) fn directive_invert() -> GeneratedBrillig { rhs: input, destination: input, }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 1 }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: one_usize }, + }, ], name: "directive_invert".to_string(), ..Default::default() @@ -129,9 +136,141 @@ pub(crate) fn directive_quotient() -> GeneratedBrillig { destination: MemoryAddress::direct(0), source: MemoryAddress::direct(2), }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 2 }, + BrilligOpcode::Stop { + return_data: HeapVector { + pointer: MemoryAddress::direct(11), + size: MemoryAddress::direct(10), + }, + }, ], name: "directive_integer_quotient".to_string(), ..Default::default() } } + +/// Generates brillig bytecode which performs a radix-base decomposition of `a` +/// The brillig inputs are 'a', the numbers of limbs and the radix +pub(crate) fn directive_to_radix() -> GeneratedBrillig { + let memory_adr_int_size = IntegerBitSize::U32; + let memory_adr_size = BitSize::Integer(memory_adr_int_size); + + // (0) is the input field `a` to decompose + // (1) contains the number of limbs (second input) + let limbs_nb = MemoryAddress::direct(1); + // (2) contains the radix (third input) + let radix = MemoryAddress::direct(2); + // (3) and (4) are intermediate registers + // (5,6,7) are constants: 0,1,3 + let zero = MemoryAddress::direct(5); + let one = MemoryAddress::direct(6); + let three = MemoryAddress::direct(7); + // (7) is the iteration bound, it is the same register as three because the latter is only used at the start + let bound = MemoryAddress::direct(7); + // (8) is the register for storing the loop condition + let cond = MemoryAddress::direct(8); + // (9) is the pointer to the result array + let result_pointer = MemoryAddress::direct(9); + // address of the result array + let result_base_adr = 10_usize; + + let result_vector = HeapVector { pointer: result_pointer, size: limbs_nb }; + + let byte_code = vec![ + // Initialize registers + // Constants + // Zero + BrilligOpcode::Const { destination: zero, bit_size: memory_adr_size, value: F::zero() }, + // One + BrilligOpcode::Const { + destination: one, + bit_size: memory_adr_size, + value: F::from(1_usize), + }, + // Three + BrilligOpcode::Const { + destination: three, + bit_size: memory_adr_size, + value: F::from(3_usize), + }, + // Brillig Inputs + BrilligOpcode::CalldataCopy { + destination_address: MemoryAddress::direct(0), + size_address: three, + offset_address: zero, + }, + // The number of limbs needs to be an integer + BrilligOpcode::Cast { destination: limbs_nb, source: limbs_nb, bit_size: memory_adr_size }, + // Result_pointer starts at the base address + BrilligOpcode::Const { + destination: result_pointer, + bit_size: memory_adr_size, + value: F::from(result_base_adr), + }, + // Loop bound + BrilligOpcode::BinaryIntOp { + destination: bound, + op: BinaryIntOp::Add, + bit_size: memory_adr_int_size, + lhs: result_pointer, + rhs: limbs_nb, + }, + // loop label: (3) = a / radix (integer division) + BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::IntegerDiv, + lhs: MemoryAddress::direct(0), + rhs: radix, + destination: MemoryAddress::direct(3), + }, + //(4) = (3)*256 + BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Mul, + lhs: MemoryAddress::direct(3), + rhs: radix, + destination: MemoryAddress::direct(4), + }, + //(4) = a-(3)*256 (remainder) + BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Sub, + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(4), + destination: MemoryAddress::direct(4), + }, + // Store the remainder in the result array + BrilligOpcode::Store { + destination_pointer: result_pointer, + source: MemoryAddress::direct(4), + }, + // Increment the result pointer + BrilligOpcode::BinaryIntOp { + op: BinaryIntOp::Add, + lhs: result_pointer, + rhs: one, + destination: result_pointer, + bit_size: memory_adr_int_size, + }, + //a := quotient + BrilligOpcode::Mov { + destination: MemoryAddress::direct(0), + source: MemoryAddress::direct(3), + }, + // loop condition + BrilligOpcode::BinaryIntOp { + op: BinaryIntOp::LessThan, + lhs: result_pointer, + rhs: bound, + destination: cond, + bit_size: memory_adr_int_size, + }, + // loop back + BrilligOpcode::JumpIf { condition: cond, location: 7 }, + // reset result pointer to the start of the array + BrilligOpcode::Const { + destination: result_pointer, + bit_size: memory_adr_size, + value: F::from(result_base_adr), + }, + BrilligOpcode::Stop { return_data: result_vector }, + ]; + + GeneratedBrillig { byte_code, name: "directive_to_radix".to_string(), ..Default::default() } +} diff --git a/compiler/noirc_evaluator/src/acir/generated_acir.rs b/compiler/noirc_evaluator/src/acir/generated_acir.rs index 09653d5b73b..91206abe732 100644 --- a/compiler/noirc_evaluator/src/acir/generated_acir.rs +++ b/compiler/noirc_evaluator/src/acir/generated_acir.rs @@ -6,14 +6,10 @@ use acvm::acir::{ circuit::{ brillig::{BrilligFunctionId, BrilligInputs, BrilligOutputs}, opcodes::{BlackBoxFuncCall, FunctionInput, Opcode as AcirOpcode}, - AssertionPayload, BrilligOpcodeLocation, OpcodeLocation, + AssertionPayload, BrilligOpcodeLocation, ErrorSelector, OpcodeLocation, }, - native_types::Witness, - BlackBoxFunc, -}; -use acvm::{ - acir::AcirField, - acir::{circuit::directives::Directive, native_types::Expression}, + native_types::{Expression, Witness}, + AcirField, BlackBoxFunc, }; use super::brillig_directive; @@ -21,6 +17,7 @@ use crate::{ brillig::brillig_ir::artifact::GeneratedBrillig, errors::{InternalError, RuntimeError, SsaReport}, ssa::ir::dfg::CallStack, + ErrorType, }; use iter_extended::vecmap; @@ -66,6 +63,9 @@ pub(crate) struct GeneratedAcir { /// Correspondence between an opcode index and the error message associated with it. pub(crate) assertion_payloads: BTreeMap>, + /// Correspondence between error selectors and types associated with them. + pub(crate) error_types: BTreeMap, + pub(crate) warnings: Vec, /// Name for the corresponding entry point represented by this Acir-gen output. @@ -94,6 +94,7 @@ pub(crate) type BrilligProcedureRangeMap = BTreeMap brillig_directive::directive_invert(), BrilligStdlibFunc::Quotient => brillig_directive::directive_quotient(), + BrilligStdlibFunc::ToLeBytes => brillig_directive::directive_to_radix(), } } } @@ -379,12 +381,7 @@ impl GeneratedAcir { "ICE: Radix must be a power of 2" ); - let limb_witnesses = vecmap(0..limb_count, |_| self.next_witness_index()); - self.push_opcode(AcirOpcode::Directive(Directive::ToLeRadix { - a: input_expr.clone(), - b: limb_witnesses.clone(), - radix, - })); + let limb_witnesses = self.brillig_to_radix(input_expr, radix, limb_count); let mut composed_limbs = Expression::default(); @@ -405,6 +402,54 @@ impl GeneratedAcir { Ok(limb_witnesses) } + /// Adds brillig opcode for to_radix + /// + /// This code will decompose `expr` in a radix-base + /// and return `Witnesses` which may (or not, because it does not apply constraints) + /// be limbs resulting from the decomposition. + /// + /// Safety: It is the callers responsibility to ensure that the + /// resulting `Witnesses` are properly constrained. + pub(crate) fn brillig_to_radix( + &mut self, + expr: &Expression, + radix: u32, + limb_count: u32, + ) -> Vec { + // Create the witness for the result + let limb_witnesses = vecmap(0..limb_count, |_| self.next_witness_index()); + + // Get the decomposition brillig code + let le_bytes_code = brillig_directive::directive_to_radix(); + // Prepare the inputs/outputs + let limbs_nb = Expression { + mul_terms: Vec::new(), + linear_combinations: Vec::new(), + q_c: F::from(limb_count as u128), + }; + let radix_expr = Expression { + mul_terms: Vec::new(), + linear_combinations: Vec::new(), + q_c: F::from(radix as u128), + }; + let inputs = vec![ + BrilligInputs::Single(expr.clone()), + BrilligInputs::Single(limbs_nb), + BrilligInputs::Single(radix_expr), + ]; + let outputs = vec![BrilligOutputs::Array(limb_witnesses.clone())]; + + self.brillig_call( + None, + &le_bytes_code, + inputs, + outputs, + PLACEHOLDER_BRILLIG_INDEX, + Some(BrilligStdlibFunc::ToLeBytes), + ); + limb_witnesses + } + /// Adds an inversion brillig opcode. /// /// This code will invert `expr` without applying constraints @@ -587,15 +632,8 @@ impl GeneratedAcir { return; } - // TODO(https://github.com/noir-lang/noir/issues/5792) - for (brillig_index, message) in generated_brillig.assert_messages.iter() { - self.assertion_payloads.insert( - OpcodeLocation::Brillig { - acir_index: self.opcodes.len() - 1, - brillig_index: *brillig_index, - }, - AssertionPayload::StaticString(message.clone()), - ); + for (error_selector, error_type) in generated_brillig.error_types.iter() { + self.record_error_type(*error_selector, error_type.clone()); } if inserted_func_before { @@ -638,6 +676,20 @@ impl GeneratedAcir { pub(crate) fn last_acir_opcode_location(&self) -> OpcodeLocation { OpcodeLocation::Acir(self.opcodes.len() - 1) } + + pub(crate) fn record_error_type(&mut self, selector: ErrorSelector, typ: ErrorType) { + self.error_types.insert(selector, typ); + } + + pub(crate) fn generate_assertion_message_payload( + &mut self, + message: String, + ) -> AssertionPayload { + let error_type = ErrorType::String(message); + let error_selector = error_type.selector(); + self.record_error_type(error_selector, error_type); + AssertionPayload { error_selector: error_selector.as_u64(), payload: Vec::new() } + } } /// This function will return the number of inputs that a blackbox function diff --git a/compiler/noirc_evaluator/src/acir/mod.rs b/compiler/noirc_evaluator/src/acir/mod.rs index 16b07b40863..5c7899b5035 100644 --- a/compiler/noirc_evaluator/src/acir/mod.rs +++ b/compiler/noirc_evaluator/src/acir/mod.rs @@ -39,7 +39,7 @@ use crate::ssa::{ dfg::{CallStack, DataFlowGraph}, function::{Function, FunctionId, RuntimeType}, instruction::{ - Binary, BinaryOp, ConstrainError, ErrorType, Instruction, InstructionId, Intrinsic, + Binary, BinaryOp, ConstrainError, Instruction, InstructionId, Intrinsic, TerminatorInstruction, }, map::Id, @@ -52,6 +52,7 @@ use crate::ssa::{ use acir_variable::{AcirContext, AcirType, AcirVar}; use generated_acir::BrilligStdlibFunc; pub(crate) use generated_acir::GeneratedAcir; +use noirc_frontend::hir_def::types::Type as HirType; #[derive(Default)] struct SharedContext { @@ -295,7 +296,7 @@ pub(crate) type Artifacts = ( Vec>, Vec>, Vec, - BTreeMap, + BTreeMap, ); impl Ssa { @@ -308,6 +309,7 @@ impl Ssa { let mut acirs = Vec::new(); // TODO: can we parallelize this? let mut shared_context = SharedContext::default(); + for function in self.functions.values() { let context = Context::new(&mut shared_context, expression_width); if let Some(mut generated_acir) = @@ -687,16 +689,19 @@ impl<'a> Context<'a> { let assert_payload = if let Some(error) = assert_message { match error { - ConstrainError::StaticString(string) => { - Some(AssertionPayload::StaticString(string.clone())) - } - ConstrainError::Dynamic(error_selector, values) => { + ConstrainError::StaticString(string) => Some( + self.acir_context.generate_assertion_message_payload(string.clone()), + ), + ConstrainError::Dynamic(error_selector, is_string_type, values) => { if let Some(constant_string) = try_to_extract_string_from_error_payload( - *error_selector, + *is_string_type, values, dfg, ) { - Some(AssertionPayload::StaticString(constant_string)) + Some( + self.acir_context + .generate_assertion_message_payload(constant_string), + ) } else { let acir_vars: Vec<_> = values .iter() @@ -706,10 +711,10 @@ impl<'a> Context<'a> { let expressions_or_memory = self.acir_context.vars_to_expressions_or_memory(&acir_vars)?; - Some(AssertionPayload::Dynamic( - error_selector.as_u64(), - expressions_or_memory, - )) + Some(AssertionPayload { + error_selector: error_selector.as_u64(), + payload: expressions_or_memory, + }) } } } @@ -1010,7 +1015,7 @@ impl<'a> Context<'a> { // Link the entry point with all dependencies while let Some(unresolved_fn_label) = entry_point.first_unresolved_function_call() { - let artifact = &brillig.find_by_label(unresolved_fn_label); + let artifact = &brillig.find_by_label(unresolved_fn_label.clone()); let artifact = match artifact { Some(artifact) => artifact, None => { @@ -1022,13 +1027,13 @@ impl<'a> Context<'a> { }; entry_point.link_with(artifact); // Insert the range of opcode locations occupied by a procedure - if let Some(procedure_id) = artifact.procedure { + if let Some(procedure_id) = &artifact.procedure { let num_opcodes = entry_point.byte_code.len(); let previous_num_opcodes = entry_point.byte_code.len() - artifact.byte_code.len(); // We subtract one as to keep the range inclusive on both ends entry_point .procedure_locations - .insert(procedure_id, (previous_num_opcodes, num_opcodes - 1)); + .insert(procedure_id.clone(), (previous_num_opcodes, num_opcodes - 1)); } } // Generate the final bytecode diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index 9661406abee..36e1ee90e11 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -256,7 +256,7 @@ impl<'block> BrilligBlock<'block> { }; match assert_message { - Some(ConstrainError::Dynamic(selector, values)) => { + Some(ConstrainError::Dynamic(selector, _, values)) => { let payload_values = vecmap(values, |value| self.convert_ssa_value(*value, dfg)); let payload_as_params = vecmap(values, |value| { @@ -267,7 +267,7 @@ impl<'block> BrilligBlock<'block> { condition, payload_values, payload_as_params, - selector.as_u64(), + *selector, ); } Some(ConstrainError::StaticString(message)) => { diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs index 66d51b2accc..b4e10035af6 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs @@ -378,12 +378,12 @@ pub(crate) mod tests { // We push a JumpIf and Trap opcode directly as the constrain instruction // uses unresolved jumps which requires a block to be constructed in SSA and // we don't need this for Brillig IR tests - context.push_opcode(BrilligOpcode::JumpIf { condition: r_equality, location: 9 }); context.push_opcode(BrilligOpcode::Const { destination: MemoryAddress::direct(0), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }); + context.push_opcode(BrilligOpcode::JumpIf { condition: r_equality, location: 9 }); context.push_opcode(BrilligOpcode::Trap { revert_data: HeapVector { pointer: MemoryAddress::direct(0), @@ -391,7 +391,10 @@ pub(crate) mod tests { }, }); - context.stop_instruction(); + context.stop_instruction(HeapVector { + pointer: MemoryAddress::direct(0), + size: MemoryAddress::direct(0), + }); let bytecode: Vec> = context.artifact().finish().byte_code; let number_sequence: Vec = diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs index 276456fc40d..0e5b72c0b85 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs @@ -1,7 +1,9 @@ use acvm::acir::brillig::Opcode as BrilligOpcode; +use acvm::acir::circuit::ErrorSelector; use std::collections::{BTreeMap, HashMap}; use crate::ssa::ir::{basic_block::BasicBlockId, dfg::CallStack, function::FunctionId}; +use crate::ErrorType; use super::procedures::ProcedureId; @@ -23,7 +25,7 @@ pub(crate) enum BrilligParameter { pub(crate) struct GeneratedBrillig { pub(crate) byte_code: Vec>, pub(crate) locations: BTreeMap, - pub(crate) assert_messages: BTreeMap, + pub(crate) error_types: BTreeMap, pub(crate) name: String, pub(crate) procedure_locations: HashMap, } @@ -33,10 +35,7 @@ pub(crate) struct GeneratedBrillig { /// It includes the bytecode of the function and all the metadata that allows linking with other functions. pub(crate) struct BrilligArtifact { pub(crate) byte_code: Vec>, - /// A map of bytecode positions to assertion messages. - /// Some error messages (compiler intrinsics) are not emitted via revert data, - /// instead, they are handled externally so they don't add size to user programs. - pub(crate) assert_messages: BTreeMap, + pub(crate) error_types: BTreeMap, /// The set of jumps that need to have their locations /// resolved. unresolved_jumps: Vec<(JumpInstructionPosition, UnresolvedJumpLocation)>, @@ -68,7 +67,7 @@ pub(crate) struct BrilligArtifact { /// A pointer to a location in the opcode. pub(crate) type OpcodeLocation = usize; -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, PartialEq, Hash)] pub(crate) enum LabelType { /// Labels for the entry point bytecode Entrypoint, @@ -98,7 +97,7 @@ impl std::fmt::Display for LabelType { /// /// It is assumed that an entity will keep a map /// of labels to Opcode locations. -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, PartialEq, Hash)] pub(crate) struct Label { pub(crate) label_type: LabelType, pub(crate) section: Option, @@ -106,7 +105,7 @@ pub(crate) struct Label { impl Label { pub(crate) fn add_section(&self, section: usize) -> Self { - Label { label_type: self.label_type, section: Some(section) } + Label { label_type: self.label_type.clone(), section: Some(section) } } pub(crate) fn function(func_id: FunctionId) -> Self { @@ -157,7 +156,7 @@ impl BrilligArtifact { GeneratedBrillig { byte_code: self.byte_code, locations: self.locations, - assert_messages: self.assert_messages, + error_types: self.error_types, name: self.name, procedure_locations: self.procedure_locations, } @@ -165,7 +164,7 @@ impl BrilligArtifact { /// Gets the first unresolved function call of this artifact. pub(crate) fn first_unresolved_function_call(&self) -> Option