diff --git a/.github/workflows/test-js-packages.yml b/.github/workflows/test-js-packages.yml index 774aa4f651d..abf6e6f3e16 100644 --- a/.github/workflows/test-js-packages.yml +++ b/.github/workflows/test-js-packages.yml @@ -512,54 +512,56 @@ jobs: run: | yarn test:node - test-integration-browser: - name: Integration Tests (Browser) - runs-on: ubuntu-22.04 - needs: [build-acvm-js, build-noir-wasm, build-noirc-abi] - timeout-minutes: 30 - permissions: - contents: read - - steps: - - name: Checkout - uses: actions/checkout@v5 - - - name: Download acvm_js package artifact - uses: actions/download-artifact@v4 - with: - name: acvm-js - path: ./acvm-repo/acvm_js - - - name: Download noir_wasm package artifact - uses: actions/download-artifact@v4 - with: - name: noir_wasm - path: ./compiler/wasm - - - name: Download noirc_abi package artifact - uses: actions/download-artifact@v4 - with: - name: noirc_abi_wasm - path: ./tooling/noirc_abi_wasm - - - name: Install Yarn dependencies - uses: ./.github/actions/setup - - - uses: taiki-e/install-action@just - - - name: Install Playwright - run: just install-playwright - - - name: Setup `integration-tests` - run: | - # Note the lack of spaces between package names. - PACKAGES_TO_BUILD="@noir-lang/types,@noir-lang/noir_js" - yarn workspaces foreach -Wvtp --from "{$PACKAGES_TO_BUILD}" run build - - - name: Run `integration-tests` - working-directory: ./compiler/integration-tests - run: | - yarn test:browser + # TODO(https://github.com/noir-lang/noir/issues/9935): These tests are currently broken as they are currently written + # We have other browser tests under `examples/browser`, but it would be good to get these working again. + # test-integration-browser: + # name: Integration Tests (Browser) + # runs-on: ubuntu-22.04 + # needs: [build-acvm-js, build-noir-wasm, build-noirc-abi] + # timeout-minutes: 30 + # permissions: + # contents: read + + # steps: + # - name: Checkout + # uses: actions/checkout@v5 + + # - name: Download acvm_js package artifact + # uses: actions/download-artifact@v4 + # with: + # name: acvm-js + # path: ./acvm-repo/acvm_js + + # - name: Download noir_wasm package artifact + # uses: actions/download-artifact@v4 + # with: + # name: noir_wasm + # path: ./compiler/wasm + + # - name: Download noirc_abi package artifact + # uses: actions/download-artifact@v4 + # with: + # name: noirc_abi_wasm + # path: ./tooling/noirc_abi_wasm + + # - name: Install Yarn dependencies + # uses: ./.github/actions/setup + + # - uses: taiki-e/install-action@just + + # - name: Install Playwright + # run: just install-playwright + + # - name: Setup `integration-tests` + # run: | + # # Note the lack of spaces between package names. + # PACKAGES_TO_BUILD="@noir-lang/types,@noir-lang/noir_js" + # yarn workspaces foreach -Wvtp --from "{$PACKAGES_TO_BUILD}" run build + + # - name: Run `integration-tests` + # working-directory: ./compiler/integration-tests + # run: | + # yarn test:browser test-examples: name: Example scripts @@ -801,7 +803,7 @@ jobs: - test-noir-wasm - test-noir-codegen - test-integration-node - - test-integration-browser + #- test-integration-browser - test-examples - compile-noir-contracts permissions: diff --git a/Cargo.lock b/Cargo.lock index a22d6e166f4..a92abe0d05d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -94,7 +94,6 @@ dependencies = [ "keccak", "libaes", "log", - "num-bigint", "num-prime", "p256", "proptest", @@ -846,11 +845,9 @@ name = "brillig" version = "1.0.0-beta.13" dependencies = [ "acir_field", - "num-bigint", "proptest", "proptest-derive", "serde", - "serde_json", ] [[package]] @@ -3263,6 +3260,9 @@ dependencies = [ "noirc_errors", "noirc_frontend", "noirc_printable_type", + "num-bigint", + "proptest", + "proptest-derive", "rand 0.8.5", "rayon", "serde", diff --git a/EXTERNAL_NOIR_LIBRARIES.yml b/EXTERNAL_NOIR_LIBRARIES.yml index de66e0753db..544e715b0e7 100644 --- a/EXTERNAL_NOIR_LIBRARIES.yml +++ b/EXTERNAL_NOIR_LIBRARIES.yml @@ -46,7 +46,7 @@ libraries: critical: true sparse_array: repo: noir-lang/sparse_array - timeout: 3 + timeout: 10 critical: false noir_json_parser: repo: noir-lang/noir_json_parser diff --git a/acvm-repo/acir/benches/serialization.rs b/acvm-repo/acir/benches/serialization.rs index 2725b3e1dd0..22dbc858e24 100644 --- a/acvm-repo/acir/benches/serialization.rs +++ b/acvm-repo/acir/benches/serialization.rs @@ -3,7 +3,7 @@ use std::{collections::BTreeSet, time::Duration}; use acir::{ FieldElement, - circuit::{Circuit, ExpressionWidth, Opcode, Program, PublicInputs}, + circuit::{Circuit, Opcode, Program, PublicInputs}, native_types::{Expression, Witness}, }; @@ -31,9 +31,9 @@ fn sample_program(num_opcodes: usize) -> Program { Program { functions: vec![Circuit { + function_name: "main".to_string(), current_witness_index: 4000, opcodes: assert_zero_opcodes.to_vec(), - expression_width: ExpressionWidth::Bounded { width: 4 }, private_parameters: BTreeSet::from([Witness(1), Witness(2), Witness(3), Witness(4)]), public_parameters: PublicInputs(BTreeSet::from([Witness(5)])), return_values: PublicInputs(BTreeSet::from([Witness(6)])), diff --git a/acvm-repo/acir/codegen/acir.cpp b/acvm-repo/acir/codegen/acir.cpp index ffb51576a66..973963029f3 100644 --- a/acvm-repo/acir/codegen/acir.cpp +++ b/acvm-repo/acir/codegen/acir.cpp @@ -1148,167 +1148,18 @@ namespace Acir { } }; - struct BigIntAdd { - Acir::MemoryAddress lhs; - Acir::MemoryAddress rhs; - Acir::MemoryAddress output; - - friend bool operator==(const BigIntAdd&, const BigIntAdd&); - std::vector bincodeSerialize() const; - static BigIntAdd bincodeDeserialize(std::vector); - - void msgpack_pack(auto& packer) const { - packer.pack_map(3); - packer.pack(std::make_pair("lhs", lhs)); - packer.pack(std::make_pair("rhs", rhs)); - packer.pack(std::make_pair("output", output)); - } - - void msgpack_unpack(msgpack::object const& o) { - auto name = "BigIntAdd"; - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "lhs", lhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "rhs", rhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); - } - }; - - struct BigIntSub { - Acir::MemoryAddress lhs; - Acir::MemoryAddress rhs; - Acir::MemoryAddress output; - - friend bool operator==(const BigIntSub&, const BigIntSub&); - std::vector bincodeSerialize() const; - static BigIntSub bincodeDeserialize(std::vector); - - void msgpack_pack(auto& packer) const { - packer.pack_map(3); - packer.pack(std::make_pair("lhs", lhs)); - packer.pack(std::make_pair("rhs", rhs)); - packer.pack(std::make_pair("output", output)); - } - - void msgpack_unpack(msgpack::object const& o) { - auto name = "BigIntSub"; - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "lhs", lhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "rhs", rhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); - } - }; - - struct BigIntMul { - Acir::MemoryAddress lhs; - Acir::MemoryAddress rhs; - Acir::MemoryAddress output; - - friend bool operator==(const BigIntMul&, const BigIntMul&); - std::vector bincodeSerialize() const; - static BigIntMul bincodeDeserialize(std::vector); - - void msgpack_pack(auto& packer) const { - packer.pack_map(3); - packer.pack(std::make_pair("lhs", lhs)); - packer.pack(std::make_pair("rhs", rhs)); - packer.pack(std::make_pair("output", output)); - } - - void msgpack_unpack(msgpack::object const& o) { - auto name = "BigIntMul"; - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "lhs", lhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "rhs", rhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); - } - }; - - struct BigIntDiv { - Acir::MemoryAddress lhs; - Acir::MemoryAddress rhs; - Acir::MemoryAddress output; - - friend bool operator==(const BigIntDiv&, const BigIntDiv&); - std::vector bincodeSerialize() const; - static BigIntDiv bincodeDeserialize(std::vector); - - void msgpack_pack(auto& packer) const { - packer.pack_map(3); - packer.pack(std::make_pair("lhs", lhs)); - packer.pack(std::make_pair("rhs", rhs)); - packer.pack(std::make_pair("output", output)); - } - - void msgpack_unpack(msgpack::object const& o) { - auto name = "BigIntDiv"; - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "lhs", lhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "rhs", rhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); - } - }; - - struct BigIntFromLeBytes { - Acir::HeapVector inputs; - Acir::HeapVector modulus; - Acir::MemoryAddress output; - - friend bool operator==(const BigIntFromLeBytes&, const BigIntFromLeBytes&); - std::vector bincodeSerialize() const; - static BigIntFromLeBytes bincodeDeserialize(std::vector); - - void msgpack_pack(auto& packer) const { - packer.pack_map(3); - packer.pack(std::make_pair("inputs", inputs)); - packer.pack(std::make_pair("modulus", modulus)); - packer.pack(std::make_pair("output", output)); - } - - void msgpack_unpack(msgpack::object const& o) { - auto name = "BigIntFromLeBytes"; - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "modulus", modulus, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); - } - }; - - struct BigIntToLeBytes { - Acir::MemoryAddress input; - Acir::HeapVector output; - - friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); - std::vector bincodeSerialize() const; - static BigIntToLeBytes bincodeDeserialize(std::vector); - - void msgpack_pack(auto& packer) const { - packer.pack_map(2); - packer.pack(std::make_pair("input", input)); - packer.pack(std::make_pair("output", output)); - } - - void msgpack_unpack(msgpack::object const& o) { - auto name = "BigIntToLeBytes"; - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "input", input, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); - } - }; - struct Poseidon2Permutation { Acir::HeapVector message; Acir::HeapArray output; - Acir::MemoryAddress len; friend bool operator==(const Poseidon2Permutation&, const Poseidon2Permutation&); std::vector bincodeSerialize() const; static Poseidon2Permutation bincodeDeserialize(std::vector); void msgpack_pack(auto& packer) const { - packer.pack_map(3); + packer.pack_map(2); packer.pack(std::make_pair("message", message)); packer.pack(std::make_pair("output", output)); - packer.pack(std::make_pair("len", len)); } void msgpack_unpack(msgpack::object const& o) { @@ -1316,7 +1167,6 @@ namespace Acir { auto kvmap = Helpers::make_kvmap(o, name); Helpers::conv_fld_from_kvmap(kvmap, name, "message", message, false); Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "len", len, false); } }; @@ -1376,7 +1226,7 @@ namespace Acir { } }; - std::variant value; + std::variant value; friend bool operator==(const BlackBoxOp&, const BlackBoxOp&); std::vector bincodeSerialize() const; @@ -1420,38 +1270,14 @@ namespace Acir { is_unit = false; break; case 8: - tag = "BigIntAdd"; - is_unit = false; - break; - case 9: - tag = "BigIntSub"; - is_unit = false; - break; - case 10: - tag = "BigIntMul"; - is_unit = false; - break; - case 11: - tag = "BigIntDiv"; - is_unit = false; - break; - case 12: - tag = "BigIntFromLeBytes"; - is_unit = false; - break; - case 13: - tag = "BigIntToLeBytes"; - is_unit = false; - break; - case 14: tag = "Poseidon2Permutation"; is_unit = false; break; - case 15: + case 9: tag = "Sha256Compression"; is_unit = false; break; - case 16: + case 10: tag = "ToRadix"; is_unit = false; break; @@ -1577,72 +1403,6 @@ namespace Acir { value = v; } - else if (tag == "BigIntAdd") { - BigIntAdd v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxOp::BigIntAdd'"); - } - - value = v; - } - else if (tag == "BigIntSub") { - BigIntSub v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxOp::BigIntSub'"); - } - - value = v; - } - else if (tag == "BigIntMul") { - BigIntMul v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxOp::BigIntMul'"); - } - - value = v; - } - else if (tag == "BigIntDiv") { - BigIntDiv v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxOp::BigIntDiv'"); - } - - value = v; - } - else if (tag == "BigIntFromLeBytes") { - BigIntFromLeBytes v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxOp::BigIntFromLeBytes'"); - } - - value = v; - } - else if (tag == "BigIntToLeBytes") { - BigIntToLeBytes v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxOp::BigIntToLeBytes'"); - } - - value = v; - } else if (tag == "Poseidon2Permutation") { Poseidon2Permutation v; try { @@ -2111,28 +1871,6 @@ namespace Acir { } }; - struct JumpIfNot { - Acir::MemoryAddress condition; - uint64_t location; - - friend bool operator==(const JumpIfNot&, const JumpIfNot&); - std::vector bincodeSerialize() const; - static JumpIfNot bincodeDeserialize(std::vector); - - void msgpack_pack(auto& packer) const { - packer.pack_map(2); - packer.pack(std::make_pair("condition", condition)); - packer.pack(std::make_pair("location", location)); - } - - void msgpack_unpack(msgpack::object const& o) { - auto name = "JumpIfNot"; - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "condition", condition, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "location", location, false); - } - }; - struct JumpIf { Acir::MemoryAddress condition; uint64_t location; @@ -2221,7 +1959,7 @@ namespace Acir { struct Const { Acir::MemoryAddress destination; Acir::BitSize bit_size; - std::string value; + std::vector value; friend bool operator==(const Const&, const Const&); std::vector bincodeSerialize() const; @@ -2246,7 +1984,7 @@ namespace Acir { struct IndirectConst { Acir::MemoryAddress destination_pointer; Acir::BitSize bit_size; - std::string value; + std::vector value; friend bool operator==(const IndirectConst&, const IndirectConst&); std::vector bincodeSerialize() const; @@ -2459,7 +2197,7 @@ namespace Acir { } }; - std::variant value; + std::variant value; friend bool operator==(const BrilligOpcode&, const BrilligOpcode&); std::vector bincodeSerialize() const; @@ -2487,66 +2225,62 @@ namespace Acir { is_unit = false; break; case 4: - tag = "JumpIfNot"; - is_unit = false; - break; - case 5: tag = "JumpIf"; is_unit = false; break; - case 6: + case 5: tag = "Jump"; is_unit = false; break; - case 7: + case 6: tag = "CalldataCopy"; is_unit = false; break; - case 8: + case 7: tag = "Call"; is_unit = false; break; - case 9: + case 8: tag = "Const"; is_unit = false; break; - case 10: + case 9: tag = "IndirectConst"; is_unit = false; break; - case 11: + case 10: tag = "Return"; is_unit = true; break; - case 12: + case 11: tag = "ForeignCall"; is_unit = false; break; - case 13: + case 12: tag = "Mov"; is_unit = false; break; - case 14: + case 13: tag = "ConditionalMov"; is_unit = false; break; - case 15: + case 14: tag = "Load"; is_unit = false; break; - case 16: + case 15: tag = "Store"; is_unit = false; break; - case 17: + case 16: tag = "BlackBox"; is_unit = false; break; - case 18: + case 17: tag = "Trap"; is_unit = false; break; - case 19: + case 18: tag = "Stop"; is_unit = false; break; @@ -2628,17 +2362,6 @@ namespace Acir { value = v; } - else if (tag == "JumpIfNot") { - JumpIfNot v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BrilligOpcode::JumpIfNot'"); - } - - value = v; - } else if (tag == "JumpIf") { JumpIf v; try { @@ -2823,10 +2546,10 @@ namespace Acir { } }; - struct ConstantOrWitnessEnum { + struct FunctionInput { struct Constant { - std::string value; + std::vector value; friend bool operator==(const Constant&, const Constant&); std::vector bincodeSerialize() const; @@ -2865,9 +2588,9 @@ namespace Acir { std::variant value; - friend bool operator==(const ConstantOrWitnessEnum&, const ConstantOrWitnessEnum&); + friend bool operator==(const FunctionInput&, const FunctionInput&); std::vector bincodeSerialize() const; - static ConstantOrWitnessEnum bincodeDeserialize(std::vector); + static FunctionInput bincodeDeserialize(std::vector); void msgpack_pack(auto& packer) const { std::string tag; @@ -2883,7 +2606,7 @@ namespace Acir { is_unit = false; break; default: - throw_or_abort("unknown enum 'ConstantOrWitnessEnum' variant index: " + std::to_string(value.index())); + throw_or_abort("unknown enum 'FunctionInput' variant index: " + std::to_string(value.index())); } if (is_unit) { packer.pack(tag); @@ -2900,10 +2623,10 @@ namespace Acir { if (o.type != msgpack::type::object_type::MAP && o.type != msgpack::type::object_type::STR) { std::cerr << o << std::endl; - throw_or_abort("expected MAP or STR for enum 'ConstantOrWitnessEnum'; got type " + std::to_string(o.type)); + throw_or_abort("expected MAP or STR for enum 'FunctionInput'; got type " + std::to_string(o.type)); } if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { - throw_or_abort("expected 1 entry for enum 'ConstantOrWitnessEnum'; got " + std::to_string(o.via.map.size)); + throw_or_abort("expected 1 entry for enum 'FunctionInput'; got " + std::to_string(o.via.map.size)); } std::string tag; try { @@ -2914,7 +2637,7 @@ namespace Acir { } } catch(const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'ConstantOrWitnessEnum'"); + throw_or_abort("error converting tag to string for enum 'FunctionInput'"); } if (tag == "Constant") { Constant v; @@ -2922,7 +2645,7 @@ namespace Acir { o.via.map.ptr[0].val.convert(v); } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'ConstantOrWitnessEnum::Constant'"); + throw_or_abort("error converting into enum variant 'FunctionInput::Constant'"); } value = v; @@ -2933,47 +2656,25 @@ namespace Acir { o.via.map.ptr[0].val.convert(v); } catch (const msgpack::type_error&) { std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'ConstantOrWitnessEnum::Witness'"); + throw_or_abort("error converting into enum variant 'FunctionInput::Witness'"); } value = v; } else { std::cerr << o << std::endl; - throw_or_abort("unknown 'ConstantOrWitnessEnum' enum variant: " + tag); + throw_or_abort("unknown 'FunctionInput' enum variant: " + tag); } } }; - struct FunctionInput { - Acir::ConstantOrWitnessEnum input; - uint32_t num_bits; + struct BlackBoxFuncCall { - friend bool operator==(const FunctionInput&, const FunctionInput&); - std::vector bincodeSerialize() const; - static FunctionInput bincodeDeserialize(std::vector); - - void msgpack_pack(auto& packer) const { - packer.pack_map(2); - packer.pack(std::make_pair("input", input)); - packer.pack(std::make_pair("num_bits", num_bits)); - } - - void msgpack_unpack(msgpack::object const& o) { - auto name = "FunctionInput"; - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "input", input, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "num_bits", num_bits, false); - } - }; - - struct BlackBoxFuncCall { - - struct AES128Encrypt { - std::vector inputs; - std::shared_ptr> iv; - std::shared_ptr> key; - std::vector outputs; + struct AES128Encrypt { + std::vector inputs; + std::shared_ptr> iv; + std::shared_ptr> key; + std::vector outputs; friend bool operator==(const AES128Encrypt&, const AES128Encrypt&); std::vector bincodeSerialize() const; @@ -3000,6 +2701,7 @@ namespace Acir { struct AND { Acir::FunctionInput lhs; Acir::FunctionInput rhs; + uint32_t num_bits; Acir::Witness output; friend bool operator==(const AND&, const AND&); @@ -3007,9 +2709,10 @@ namespace Acir { static AND bincodeDeserialize(std::vector); void msgpack_pack(auto& packer) const { - packer.pack_map(3); + packer.pack_map(4); packer.pack(std::make_pair("lhs", lhs)); packer.pack(std::make_pair("rhs", rhs)); + packer.pack(std::make_pair("num_bits", num_bits)); packer.pack(std::make_pair("output", output)); } @@ -3018,6 +2721,7 @@ namespace Acir { auto kvmap = Helpers::make_kvmap(o, name); Helpers::conv_fld_from_kvmap(kvmap, name, "lhs", lhs, false); Helpers::conv_fld_from_kvmap(kvmap, name, "rhs", rhs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "num_bits", num_bits, false); Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); } }; @@ -3025,6 +2729,7 @@ namespace Acir { struct XOR { Acir::FunctionInput lhs; Acir::FunctionInput rhs; + uint32_t num_bits; Acir::Witness output; friend bool operator==(const XOR&, const XOR&); @@ -3032,9 +2737,10 @@ namespace Acir { static XOR bincodeDeserialize(std::vector); void msgpack_pack(auto& packer) const { - packer.pack_map(3); + packer.pack_map(4); packer.pack(std::make_pair("lhs", lhs)); packer.pack(std::make_pair("rhs", rhs)); + packer.pack(std::make_pair("num_bits", num_bits)); packer.pack(std::make_pair("output", output)); } @@ -3043,26 +2749,30 @@ namespace Acir { auto kvmap = Helpers::make_kvmap(o, name); Helpers::conv_fld_from_kvmap(kvmap, name, "lhs", lhs, false); Helpers::conv_fld_from_kvmap(kvmap, name, "rhs", rhs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "num_bits", num_bits, false); Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); } }; struct RANGE { Acir::FunctionInput input; + uint32_t num_bits; friend bool operator==(const RANGE&, const RANGE&); std::vector bincodeSerialize() const; static RANGE bincodeDeserialize(std::vector); void msgpack_pack(auto& packer) const { - packer.pack_map(1); + packer.pack_map(2); packer.pack(std::make_pair("input", input)); + packer.pack(std::make_pair("num_bits", num_bits)); } void msgpack_unpack(msgpack::object const& o) { auto name = "RANGE"; auto kvmap = Helpers::make_kvmap(o, name); Helpers::conv_fld_from_kvmap(kvmap, name, "input", input, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "num_bits", num_bits, false); } }; @@ -3115,6 +2825,7 @@ namespace Acir { std::shared_ptr> public_key_y; std::shared_ptr> signature; std::shared_ptr> hashed_message; + Acir::FunctionInput predicate; Acir::Witness output; friend bool operator==(const EcdsaSecp256k1&, const EcdsaSecp256k1&); @@ -3122,11 +2833,12 @@ namespace Acir { static EcdsaSecp256k1 bincodeDeserialize(std::vector); void msgpack_pack(auto& packer) const { - packer.pack_map(5); + packer.pack_map(6); packer.pack(std::make_pair("public_key_x", public_key_x)); packer.pack(std::make_pair("public_key_y", public_key_y)); packer.pack(std::make_pair("signature", signature)); packer.pack(std::make_pair("hashed_message", hashed_message)); + packer.pack(std::make_pair("predicate", predicate)); packer.pack(std::make_pair("output", output)); } @@ -3137,6 +2849,7 @@ namespace Acir { Helpers::conv_fld_from_kvmap(kvmap, name, "public_key_y", public_key_y, false); Helpers::conv_fld_from_kvmap(kvmap, name, "signature", signature, false); Helpers::conv_fld_from_kvmap(kvmap, name, "hashed_message", hashed_message, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); } }; @@ -3146,6 +2859,7 @@ namespace Acir { std::shared_ptr> public_key_y; std::shared_ptr> signature; std::shared_ptr> hashed_message; + Acir::FunctionInput predicate; Acir::Witness output; friend bool operator==(const EcdsaSecp256r1&, const EcdsaSecp256r1&); @@ -3153,11 +2867,12 @@ namespace Acir { static EcdsaSecp256r1 bincodeDeserialize(std::vector); void msgpack_pack(auto& packer) const { - packer.pack_map(5); + packer.pack_map(6); packer.pack(std::make_pair("public_key_x", public_key_x)); packer.pack(std::make_pair("public_key_y", public_key_y)); packer.pack(std::make_pair("signature", signature)); packer.pack(std::make_pair("hashed_message", hashed_message)); + packer.pack(std::make_pair("predicate", predicate)); packer.pack(std::make_pair("output", output)); } @@ -3168,6 +2883,7 @@ namespace Acir { Helpers::conv_fld_from_kvmap(kvmap, name, "public_key_y", public_key_y, false); Helpers::conv_fld_from_kvmap(kvmap, name, "signature", signature, false); Helpers::conv_fld_from_kvmap(kvmap, name, "hashed_message", hashed_message, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); } }; @@ -3175,6 +2891,7 @@ namespace Acir { struct MultiScalarMul { std::vector points; std::vector scalars; + Acir::FunctionInput predicate; std::shared_ptr> outputs; friend bool operator==(const MultiScalarMul&, const MultiScalarMul&); @@ -3182,9 +2899,10 @@ namespace Acir { static MultiScalarMul bincodeDeserialize(std::vector); void msgpack_pack(auto& packer) const { - packer.pack_map(3); + packer.pack_map(4); packer.pack(std::make_pair("points", points)); packer.pack(std::make_pair("scalars", scalars)); + packer.pack(std::make_pair("predicate", predicate)); packer.pack(std::make_pair("outputs", outputs)); } @@ -3193,6 +2911,7 @@ namespace Acir { auto kvmap = Helpers::make_kvmap(o, name); Helpers::conv_fld_from_kvmap(kvmap, name, "points", points, false); Helpers::conv_fld_from_kvmap(kvmap, name, "scalars", scalars, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); } }; @@ -3200,6 +2919,7 @@ namespace Acir { struct EmbeddedCurveAdd { std::shared_ptr> input1; std::shared_ptr> input2; + Acir::FunctionInput predicate; std::shared_ptr> outputs; friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); @@ -3207,9 +2927,10 @@ namespace Acir { static EmbeddedCurveAdd bincodeDeserialize(std::vector); void msgpack_pack(auto& packer) const { - packer.pack_map(3); + packer.pack_map(4); packer.pack(std::make_pair("input1", input1)); packer.pack(std::make_pair("input2", input2)); + packer.pack(std::make_pair("predicate", predicate)); packer.pack(std::make_pair("outputs", outputs)); } @@ -3218,6 +2939,7 @@ namespace Acir { auto kvmap = Helpers::make_kvmap(o, name); Helpers::conv_fld_from_kvmap(kvmap, name, "input1", input1, false); Helpers::conv_fld_from_kvmap(kvmap, name, "input2", input2, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); } }; @@ -3250,18 +2972,20 @@ namespace Acir { std::vector public_inputs; Acir::FunctionInput key_hash; uint32_t proof_type; + Acir::FunctionInput predicate; friend bool operator==(const RecursiveAggregation&, const RecursiveAggregation&); std::vector bincodeSerialize() const; static RecursiveAggregation bincodeDeserialize(std::vector); void msgpack_pack(auto& packer) const { - packer.pack_map(5); + packer.pack_map(6); packer.pack(std::make_pair("verification_key", verification_key)); packer.pack(std::make_pair("proof", proof)); packer.pack(std::make_pair("public_inputs", public_inputs)); packer.pack(std::make_pair("key_hash", key_hash)); packer.pack(std::make_pair("proof_type", proof_type)); + packer.pack(std::make_pair("predicate", predicate)); } void msgpack_unpack(msgpack::object const& o) { @@ -3272,170 +2996,22 @@ namespace Acir { Helpers::conv_fld_from_kvmap(kvmap, name, "public_inputs", public_inputs, false); Helpers::conv_fld_from_kvmap(kvmap, name, "key_hash", key_hash, false); Helpers::conv_fld_from_kvmap(kvmap, name, "proof_type", proof_type, false); - } - }; - - struct BigIntAdd { - uint32_t lhs; - uint32_t rhs; - uint32_t output; - - friend bool operator==(const BigIntAdd&, const BigIntAdd&); - std::vector bincodeSerialize() const; - static BigIntAdd bincodeDeserialize(std::vector); - - void msgpack_pack(auto& packer) const { - packer.pack_map(3); - packer.pack(std::make_pair("lhs", lhs)); - packer.pack(std::make_pair("rhs", rhs)); - packer.pack(std::make_pair("output", output)); - } - - void msgpack_unpack(msgpack::object const& o) { - auto name = "BigIntAdd"; - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "lhs", lhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "rhs", rhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); - } - }; - - struct BigIntSub { - uint32_t lhs; - uint32_t rhs; - uint32_t output; - - friend bool operator==(const BigIntSub&, const BigIntSub&); - std::vector bincodeSerialize() const; - static BigIntSub bincodeDeserialize(std::vector); - - void msgpack_pack(auto& packer) const { - packer.pack_map(3); - packer.pack(std::make_pair("lhs", lhs)); - packer.pack(std::make_pair("rhs", rhs)); - packer.pack(std::make_pair("output", output)); - } - - void msgpack_unpack(msgpack::object const& o) { - auto name = "BigIntSub"; - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "lhs", lhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "rhs", rhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); - } - }; - - struct BigIntMul { - uint32_t lhs; - uint32_t rhs; - uint32_t output; - - friend bool operator==(const BigIntMul&, const BigIntMul&); - std::vector bincodeSerialize() const; - static BigIntMul bincodeDeserialize(std::vector); - - void msgpack_pack(auto& packer) const { - packer.pack_map(3); - packer.pack(std::make_pair("lhs", lhs)); - packer.pack(std::make_pair("rhs", rhs)); - packer.pack(std::make_pair("output", output)); - } - - void msgpack_unpack(msgpack::object const& o) { - auto name = "BigIntMul"; - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "lhs", lhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "rhs", rhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); - } - }; - - struct BigIntDiv { - uint32_t lhs; - uint32_t rhs; - uint32_t output; - - friend bool operator==(const BigIntDiv&, const BigIntDiv&); - std::vector bincodeSerialize() const; - static BigIntDiv bincodeDeserialize(std::vector); - - void msgpack_pack(auto& packer) const { - packer.pack_map(3); - packer.pack(std::make_pair("lhs", lhs)); - packer.pack(std::make_pair("rhs", rhs)); - packer.pack(std::make_pair("output", output)); - } - - void msgpack_unpack(msgpack::object const& o) { - auto name = "BigIntDiv"; - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "lhs", lhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "rhs", rhs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); - } - }; - - struct BigIntFromLeBytes { - std::vector inputs; - std::vector modulus; - uint32_t output; - - friend bool operator==(const BigIntFromLeBytes&, const BigIntFromLeBytes&); - std::vector bincodeSerialize() const; - static BigIntFromLeBytes bincodeDeserialize(std::vector); - - void msgpack_pack(auto& packer) const { - packer.pack_map(3); - packer.pack(std::make_pair("inputs", inputs)); - packer.pack(std::make_pair("modulus", modulus)); - packer.pack(std::make_pair("output", output)); - } - - void msgpack_unpack(msgpack::object const& o) { - auto name = "BigIntFromLeBytes"; - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "modulus", modulus, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "output", output, false); - } - }; - - struct BigIntToLeBytes { - uint32_t input; - std::vector outputs; - - friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); - std::vector bincodeSerialize() const; - static BigIntToLeBytes bincodeDeserialize(std::vector); - - void msgpack_pack(auto& packer) const { - packer.pack_map(2); - packer.pack(std::make_pair("input", input)); - packer.pack(std::make_pair("outputs", outputs)); - } - - void msgpack_unpack(msgpack::object const& o) { - auto name = "BigIntToLeBytes"; - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "input", input, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, false); } }; struct Poseidon2Permutation { std::vector inputs; std::vector outputs; - uint32_t len; friend bool operator==(const Poseidon2Permutation&, const Poseidon2Permutation&); std::vector bincodeSerialize() const; static Poseidon2Permutation bincodeDeserialize(std::vector); void msgpack_pack(auto& packer) const { - packer.pack_map(3); + packer.pack_map(2); packer.pack(std::make_pair("inputs", inputs)); packer.pack(std::make_pair("outputs", outputs)); - packer.pack(std::make_pair("len", len)); } void msgpack_unpack(msgpack::object const& o) { @@ -3443,7 +3019,6 @@ namespace Acir { auto kvmap = Helpers::make_kvmap(o, name); Helpers::conv_fld_from_kvmap(kvmap, name, "inputs", inputs, false); Helpers::conv_fld_from_kvmap(kvmap, name, "outputs", outputs, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "len", len, false); } }; @@ -3472,7 +3047,7 @@ namespace Acir { } }; - std::variant value; + std::variant value; friend bool operator==(const BlackBoxFuncCall&, const BlackBoxFuncCall&); std::vector bincodeSerialize() const; @@ -3532,34 +3107,10 @@ namespace Acir { is_unit = false; break; case 12: - tag = "BigIntAdd"; - is_unit = false; - break; - case 13: - tag = "BigIntSub"; - is_unit = false; - break; - case 14: - tag = "BigIntMul"; - is_unit = false; - break; - case 15: - tag = "BigIntDiv"; - is_unit = false; - break; - case 16: - tag = "BigIntFromLeBytes"; - is_unit = false; - break; - case 17: - tag = "BigIntToLeBytes"; - is_unit = false; - break; - case 18: tag = "Poseidon2Permutation"; is_unit = false; break; - case 19: + case 13: tag = "Sha256Compression"; is_unit = false; break; @@ -3729,72 +3280,6 @@ namespace Acir { value = v; } - else if (tag == "BigIntAdd") { - BigIntAdd v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::BigIntAdd'"); - } - - value = v; - } - else if (tag == "BigIntSub") { - BigIntSub v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::BigIntSub'"); - } - - value = v; - } - else if (tag == "BigIntMul") { - BigIntMul v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::BigIntMul'"); - } - - value = v; - } - else if (tag == "BigIntDiv") { - BigIntDiv v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::BigIntDiv'"); - } - - value = v; - } - else if (tag == "BigIntFromLeBytes") { - BigIntFromLeBytes v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::BigIntFromLeBytes'"); - } - - value = v; - } - else if (tag == "BigIntToLeBytes") { - BigIntToLeBytes v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'BlackBoxFuncCall::BigIntToLeBytes'"); - } - - value = v; - } else if (tag == "Poseidon2Permutation") { Poseidon2Permutation v; try { @@ -3966,9 +3451,9 @@ namespace Acir { }; struct Expression { - std::vector> mul_terms; - std::vector> linear_combinations; - std::string q_c; + std::vector, Acir::Witness, Acir::Witness>> mul_terms; + std::vector, Acir::Witness>> linear_combinations; + std::vector q_c; friend bool operator==(const Expression&, const Expression&); std::vector bincodeSerialize() const; @@ -4336,17 +3821,15 @@ namespace Acir { struct MemoryOp { Acir::BlockId block_id; Acir::MemOp op; - std::optional predicate; friend bool operator==(const MemoryOp&, const MemoryOp&); std::vector bincodeSerialize() const; static MemoryOp bincodeDeserialize(std::vector); void msgpack_pack(auto& packer) const { - packer.pack_map(3); + packer.pack_map(2); packer.pack(std::make_pair("block_id", block_id)); packer.pack(std::make_pair("op", op)); - packer.pack(std::make_pair("predicate", predicate)); } void msgpack_unpack(msgpack::object const& o) { @@ -4354,7 +3837,6 @@ namespace Acir { auto kvmap = Helpers::make_kvmap(o, name); Helpers::conv_fld_from_kvmap(kvmap, name, "block_id", block_id, false); Helpers::conv_fld_from_kvmap(kvmap, name, "op", op, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "predicate", predicate, true); } }; @@ -4725,151 +4207,46 @@ namespace Acir { } }; - struct ExpressionWidth { + struct OpcodeLocation { - struct Unbounded { - friend bool operator==(const Unbounded&, const Unbounded&); + struct Acir { + uint64_t value; + + friend bool operator==(const Acir&, const Acir&); std::vector bincodeSerialize() const; - static Unbounded bincodeDeserialize(std::vector); + static Acir bincodeDeserialize(std::vector); - void msgpack_pack(auto& packer) const {} - void msgpack_unpack(msgpack::object const& o) {} + void msgpack_pack(auto& packer) const { packer.pack(value); } + + void msgpack_unpack(msgpack::object const& o) { + try { + o.convert(value); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into newtype 'Acir'"); + } + } }; - struct Bounded { - uint64_t width; + struct Brillig { + uint64_t acir_index; + uint64_t brillig_index; - friend bool operator==(const Bounded&, const Bounded&); + friend bool operator==(const Brillig&, const Brillig&); std::vector bincodeSerialize() const; - static Bounded bincodeDeserialize(std::vector); + static Brillig bincodeDeserialize(std::vector); void msgpack_pack(auto& packer) const { - packer.pack_map(1); - packer.pack(std::make_pair("width", width)); + packer.pack_map(2); + packer.pack(std::make_pair("acir_index", acir_index)); + packer.pack(std::make_pair("brillig_index", brillig_index)); } void msgpack_unpack(msgpack::object const& o) { - auto name = "Bounded"; + auto name = "Brillig"; auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "width", width, false); - } - }; - - std::variant value; - - friend bool operator==(const ExpressionWidth&, const ExpressionWidth&); - std::vector bincodeSerialize() const; - static ExpressionWidth bincodeDeserialize(std::vector); - - void msgpack_pack(auto& packer) const { - std::string tag; - bool is_unit; - switch (value.index()) { - - case 0: - tag = "Unbounded"; - is_unit = true; - break; - case 1: - tag = "Bounded"; - is_unit = false; - break; - default: - throw_or_abort("unknown enum 'ExpressionWidth' variant index: " + std::to_string(value.index())); - } - if (is_unit) { - packer.pack(tag); - } else { - std::visit([&packer, tag](const auto& arg) { - std::map data; - data[tag] = msgpack::object(arg); - packer.pack(data); - }, value); - } - } - - void msgpack_unpack(msgpack::object const& o) { - - if (o.type != msgpack::type::object_type::MAP && o.type != msgpack::type::object_type::STR) { - std::cerr << o << std::endl; - throw_or_abort("expected MAP or STR for enum 'ExpressionWidth'; got type " + std::to_string(o.type)); - } - if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { - throw_or_abort("expected 1 entry for enum 'ExpressionWidth'; got " + std::to_string(o.via.map.size)); - } - std::string tag; - try { - if (o.type == msgpack::type::object_type::MAP) { - o.via.map.ptr[0].key.convert(tag); - } else { - o.convert(tag); - } - } catch(const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting tag to string for enum 'ExpressionWidth'"); - } - if (tag == "Unbounded") { - Unbounded v; - value = v; - } - else if (tag == "Bounded") { - Bounded v; - try { - o.via.map.ptr[0].val.convert(v); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into enum variant 'ExpressionWidth::Bounded'"); - } - - value = v; - } - else { - std::cerr << o << std::endl; - throw_or_abort("unknown 'ExpressionWidth' enum variant: " + tag); - } - } - }; - - struct OpcodeLocation { - - struct Acir { - uint64_t value; - - friend bool operator==(const Acir&, const Acir&); - std::vector bincodeSerialize() const; - static Acir bincodeDeserialize(std::vector); - - void msgpack_pack(auto& packer) const { packer.pack(value); } - - void msgpack_unpack(msgpack::object const& o) { - try { - o.convert(value); - } catch (const msgpack::type_error&) { - std::cerr << o << std::endl; - throw_or_abort("error converting into newtype 'Acir'"); - } - } - }; - - struct Brillig { - uint64_t acir_index; - uint64_t brillig_index; - - friend bool operator==(const Brillig&, const Brillig&); - std::vector bincodeSerialize() const; - static Brillig bincodeDeserialize(std::vector); - - void msgpack_pack(auto& packer) const { - packer.pack_map(2); - packer.pack(std::make_pair("acir_index", acir_index)); - packer.pack(std::make_pair("brillig_index", brillig_index)); - } - - void msgpack_unpack(msgpack::object const& o) { - auto name = "Brillig"; - auto kvmap = Helpers::make_kvmap(o, name); - Helpers::conv_fld_from_kvmap(kvmap, name, "acir_index", acir_index, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "brillig_index", brillig_index, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "acir_index", acir_index, false); + Helpers::conv_fld_from_kvmap(kvmap, name, "brillig_index", brillig_index, false); } }; @@ -4975,9 +4352,9 @@ namespace Acir { }; struct Circuit { + std::string function_name; uint32_t current_witness_index; std::vector opcodes; - Acir::ExpressionWidth expression_width; std::vector private_parameters; Acir::PublicInputs public_parameters; Acir::PublicInputs return_values; @@ -4989,9 +4366,9 @@ namespace Acir { void msgpack_pack(auto& packer) const { packer.pack_map(7); + packer.pack(std::make_pair("function_name", function_name)); packer.pack(std::make_pair("current_witness_index", current_witness_index)); packer.pack(std::make_pair("opcodes", opcodes)); - packer.pack(std::make_pair("expression_width", expression_width)); packer.pack(std::make_pair("private_parameters", private_parameters)); packer.pack(std::make_pair("public_parameters", public_parameters)); packer.pack(std::make_pair("return_values", return_values)); @@ -5001,9 +4378,9 @@ namespace Acir { void msgpack_unpack(msgpack::object const& o) { auto name = "Circuit"; auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "function_name", function_name, false); Helpers::conv_fld_from_kvmap(kvmap, name, "current_witness_index", current_witness_index, false); Helpers::conv_fld_from_kvmap(kvmap, name, "opcodes", opcodes, false); - Helpers::conv_fld_from_kvmap(kvmap, name, "expression_width", expression_width, false); Helpers::conv_fld_from_kvmap(kvmap, name, "private_parameters", private_parameters, false); Helpers::conv_fld_from_kvmap(kvmap, name, "public_parameters", public_parameters, false); Helpers::conv_fld_from_kvmap(kvmap, name, "return_values", return_values, false); @@ -5012,6 +4389,7 @@ namespace Acir { }; struct BrilligBytecode { + std::string function_name; std::vector bytecode; friend bool operator==(const BrilligBytecode&, const BrilligBytecode&); @@ -5019,13 +4397,15 @@ namespace Acir { static BrilligBytecode bincodeDeserialize(std::vector); void msgpack_pack(auto& packer) const { - packer.pack_map(1); + packer.pack_map(2); + packer.pack(std::make_pair("function_name", function_name)); packer.pack(std::make_pair("bytecode", bytecode)); } void msgpack_unpack(msgpack::object const& o) { auto name = "BrilligBytecode"; auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "function_name", function_name, false); Helpers::conv_fld_from_kvmap(kvmap, name, "bytecode", bytecode, false); } }; @@ -5071,6 +4451,111 @@ namespace Acir { } }; + struct ExpressionWidth { + + struct Unbounded { + friend bool operator==(const Unbounded&, const Unbounded&); + std::vector bincodeSerialize() const; + static Unbounded bincodeDeserialize(std::vector); + + void msgpack_pack(auto& packer) const {} + void msgpack_unpack(msgpack::object const& o) {} + }; + + struct Bounded { + uint64_t width; + + friend bool operator==(const Bounded&, const Bounded&); + std::vector bincodeSerialize() const; + static Bounded bincodeDeserialize(std::vector); + + void msgpack_pack(auto& packer) const { + packer.pack_map(1); + packer.pack(std::make_pair("width", width)); + } + + void msgpack_unpack(msgpack::object const& o) { + auto name = "Bounded"; + auto kvmap = Helpers::make_kvmap(o, name); + Helpers::conv_fld_from_kvmap(kvmap, name, "width", width, false); + } + }; + + std::variant value; + + friend bool operator==(const ExpressionWidth&, const ExpressionWidth&); + std::vector bincodeSerialize() const; + static ExpressionWidth bincodeDeserialize(std::vector); + + void msgpack_pack(auto& packer) const { + std::string tag; + bool is_unit; + switch (value.index()) { + + case 0: + tag = "Unbounded"; + is_unit = true; + break; + case 1: + tag = "Bounded"; + is_unit = false; + break; + default: + throw_or_abort("unknown enum 'ExpressionWidth' variant index: " + std::to_string(value.index())); + } + if (is_unit) { + packer.pack(tag); + } else { + std::visit([&packer, tag](const auto& arg) { + std::map data; + data[tag] = msgpack::object(arg); + packer.pack(data); + }, value); + } + } + + void msgpack_unpack(msgpack::object const& o) { + + if (o.type != msgpack::type::object_type::MAP && o.type != msgpack::type::object_type::STR) { + std::cerr << o << std::endl; + throw_or_abort("expected MAP or STR for enum 'ExpressionWidth'; got type " + std::to_string(o.type)); + } + if (o.type == msgpack::type::object_type::MAP && o.via.map.size != 1) { + throw_or_abort("expected 1 entry for enum 'ExpressionWidth'; got " + std::to_string(o.via.map.size)); + } + std::string tag; + try { + if (o.type == msgpack::type::object_type::MAP) { + o.via.map.ptr[0].key.convert(tag); + } else { + o.convert(tag); + } + } catch(const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting tag to string for enum 'ExpressionWidth'"); + } + if (tag == "Unbounded") { + Unbounded v; + value = v; + } + else if (tag == "Bounded") { + Bounded v; + try { + o.via.map.ptr[0].val.convert(v); + } catch (const msgpack::type_error&) { + std::cerr << o << std::endl; + throw_or_abort("error converting into enum variant 'ExpressionWidth::Bounded'"); + } + + value = v; + } + else { + std::cerr << o << std::endl; + throw_or_abort("unknown 'ExpressionWidth' enum variant: " + tag); + } + } + }; + } // end of namespace Acir @@ -6112,6 +5597,7 @@ namespace Acir { inline bool operator==(const BlackBoxFuncCall::AND &lhs, const BlackBoxFuncCall::AND &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } if (!(lhs.rhs == rhs.rhs)) { return false; } + if (!(lhs.num_bits == rhs.num_bits)) { return false; } if (!(lhs.output == rhs.output)) { return false; } return true; } @@ -6138,6 +5624,7 @@ template void serde::Serializable::serialize(const Acir::BlackBoxFuncCall::AND &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); + serde::Serializable::serialize(obj.num_bits, serializer); serde::Serializable::serialize(obj.output, serializer); } @@ -6147,6 +5634,7 @@ Acir::BlackBoxFuncCall::AND serde::Deserializable:: Acir::BlackBoxFuncCall::AND obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.num_bits = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } @@ -6156,6 +5644,7 @@ namespace Acir { inline bool operator==(const BlackBoxFuncCall::XOR &lhs, const BlackBoxFuncCall::XOR &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } if (!(lhs.rhs == rhs.rhs)) { return false; } + if (!(lhs.num_bits == rhs.num_bits)) { return false; } if (!(lhs.output == rhs.output)) { return false; } return true; } @@ -6182,6 +5671,7 @@ template void serde::Serializable::serialize(const Acir::BlackBoxFuncCall::XOR &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); + serde::Serializable::serialize(obj.num_bits, serializer); serde::Serializable::serialize(obj.output, serializer); } @@ -6191,6 +5681,7 @@ Acir::BlackBoxFuncCall::XOR serde::Deserializable:: Acir::BlackBoxFuncCall::XOR obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.num_bits = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } @@ -6199,6 +5690,7 @@ namespace Acir { inline bool operator==(const BlackBoxFuncCall::RANGE &lhs, const BlackBoxFuncCall::RANGE &rhs) { if (!(lhs.input == rhs.input)) { return false; } + if (!(lhs.num_bits == rhs.num_bits)) { return false; } return true; } @@ -6223,6 +5715,7 @@ template <> template void serde::Serializable::serialize(const Acir::BlackBoxFuncCall::RANGE &obj, Serializer &serializer) { serde::Serializable::serialize(obj.input, serializer); + serde::Serializable::serialize(obj.num_bits, serializer); } template <> @@ -6230,6 +5723,7 @@ template Acir::BlackBoxFuncCall::RANGE serde::Deserializable::deserialize(Deserializer &deserializer) { Acir::BlackBoxFuncCall::RANGE obj; obj.input = serde::Deserializable::deserialize(deserializer); + obj.num_bits = serde::Deserializable::deserialize(deserializer); return obj; } @@ -6322,6 +5816,7 @@ namespace Acir { if (!(lhs.public_key_y == rhs.public_key_y)) { return false; } if (!(lhs.signature == rhs.signature)) { return false; } if (!(lhs.hashed_message == rhs.hashed_message)) { return false; } + if (!(lhs.predicate == rhs.predicate)) { return false; } if (!(lhs.output == rhs.output)) { return false; } return true; } @@ -6350,6 +5845,7 @@ void serde::Serializable::serialize(cons serde::Serializable::serialize(obj.public_key_y, serializer); serde::Serializable::serialize(obj.signature, serializer); serde::Serializable::serialize(obj.hashed_message, serializer); + serde::Serializable::serialize(obj.predicate, serializer); serde::Serializable::serialize(obj.output, serializer); } @@ -6361,6 +5857,7 @@ Acir::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); obj.hashed_message = serde::Deserializable::deserialize(deserializer); + obj.predicate = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } @@ -6372,6 +5869,7 @@ namespace Acir { if (!(lhs.public_key_y == rhs.public_key_y)) { return false; } if (!(lhs.signature == rhs.signature)) { return false; } if (!(lhs.hashed_message == rhs.hashed_message)) { return false; } + if (!(lhs.predicate == rhs.predicate)) { return false; } if (!(lhs.output == rhs.output)) { return false; } return true; } @@ -6400,6 +5898,7 @@ void serde::Serializable::serialize(cons serde::Serializable::serialize(obj.public_key_y, serializer); serde::Serializable::serialize(obj.signature, serializer); serde::Serializable::serialize(obj.hashed_message, serializer); + serde::Serializable::serialize(obj.predicate, serializer); serde::Serializable::serialize(obj.output, serializer); } @@ -6411,6 +5910,7 @@ Acir::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); obj.hashed_message = serde::Deserializable::deserialize(deserializer); + obj.predicate = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } @@ -6420,6 +5920,7 @@ namespace Acir { inline bool operator==(const BlackBoxFuncCall::MultiScalarMul &lhs, const BlackBoxFuncCall::MultiScalarMul &rhs) { if (!(lhs.points == rhs.points)) { return false; } if (!(lhs.scalars == rhs.scalars)) { return false; } + if (!(lhs.predicate == rhs.predicate)) { return false; } if (!(lhs.outputs == rhs.outputs)) { return false; } return true; } @@ -6446,6 +5947,7 @@ template void serde::Serializable::serialize(const Acir::BlackBoxFuncCall::MultiScalarMul &obj, Serializer &serializer) { serde::Serializable::serialize(obj.points, serializer); serde::Serializable::serialize(obj.scalars, serializer); + serde::Serializable::serialize(obj.predicate, serializer); serde::Serializable::serialize(obj.outputs, serializer); } @@ -6455,6 +5957,7 @@ Acir::BlackBoxFuncCall::MultiScalarMul serde::Deserializable::deserialize(deserializer); obj.scalars = serde::Deserializable::deserialize(deserializer); + obj.predicate = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } @@ -6464,6 +5967,7 @@ namespace Acir { inline bool operator==(const BlackBoxFuncCall::EmbeddedCurveAdd &lhs, const BlackBoxFuncCall::EmbeddedCurveAdd &rhs) { if (!(lhs.input1 == rhs.input1)) { return false; } if (!(lhs.input2 == rhs.input2)) { return false; } + if (!(lhs.predicate == rhs.predicate)) { return false; } if (!(lhs.outputs == rhs.outputs)) { return false; } return true; } @@ -6490,6 +5994,7 @@ template void serde::Serializable::serialize(const Acir::BlackBoxFuncCall::EmbeddedCurveAdd &obj, Serializer &serializer) { serde::Serializable::serialize(obj.input1, serializer); serde::Serializable::serialize(obj.input2, serializer); + serde::Serializable::serialize(obj.predicate, serializer); serde::Serializable::serialize(obj.outputs, serializer); } @@ -6499,6 +6004,7 @@ Acir::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable::deserialize(deserializer); obj.input2 = serde::Deserializable::deserialize(deserializer); + obj.predicate = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } @@ -6552,6 +6058,7 @@ namespace Acir { if (!(lhs.public_inputs == rhs.public_inputs)) { return false; } if (!(lhs.key_hash == rhs.key_hash)) { return false; } if (!(lhs.proof_type == rhs.proof_type)) { return false; } + if (!(lhs.predicate == rhs.predicate)) { return false; } return true; } @@ -6580,6 +6087,7 @@ void serde::Serializable::serializ serde::Serializable::serialize(obj.public_inputs, serializer); serde::Serializable::serialize(obj.key_hash, serializer); serde::Serializable::serialize(obj.proof_type, serializer); + serde::Serializable::serialize(obj.predicate, serializer); } template <> @@ -6591,282 +6099,21 @@ Acir::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable::deserialize(deserializer); obj.key_hash = serde::Deserializable::deserialize(deserializer); obj.proof_type = serde::Deserializable::deserialize(deserializer); + obj.predicate = serde::Deserializable::deserialize(deserializer); return obj; } namespace Acir { - inline bool operator==(const BlackBoxFuncCall::BigIntAdd &lhs, const BlackBoxFuncCall::BigIntAdd &rhs) { - if (!(lhs.lhs == rhs.lhs)) { return false; } - if (!(lhs.rhs == rhs.rhs)) { return false; } - if (!(lhs.output == rhs.output)) { return false; } + inline bool operator==(const BlackBoxFuncCall::Poseidon2Permutation &lhs, const BlackBoxFuncCall::Poseidon2Permutation &rhs) { + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } return true; } - inline std::vector BlackBoxFuncCall::BigIntAdd::bincodeSerialize() const { + inline std::vector BlackBoxFuncCall::Poseidon2Permutation::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxFuncCall::BigIntAdd BlackBoxFuncCall::BigIntAdd::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Acir - -template <> -template -void serde::Serializable::serialize(const Acir::BlackBoxFuncCall::BigIntAdd &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); - serde::Serializable::serialize(obj.output, serializer); -} - -template <> -template -Acir::BlackBoxFuncCall::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Acir::BlackBoxFuncCall::BigIntAdd obj; - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Acir { - - inline bool operator==(const BlackBoxFuncCall::BigIntSub &lhs, const BlackBoxFuncCall::BigIntSub &rhs) { - if (!(lhs.lhs == rhs.lhs)) { return false; } - if (!(lhs.rhs == rhs.rhs)) { return false; } - if (!(lhs.output == rhs.output)) { return false; } - return true; - } - - inline std::vector BlackBoxFuncCall::BigIntSub::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxFuncCall::BigIntSub BlackBoxFuncCall::BigIntSub::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Acir - -template <> -template -void serde::Serializable::serialize(const Acir::BlackBoxFuncCall::BigIntSub &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); - serde::Serializable::serialize(obj.output, serializer); -} - -template <> -template -Acir::BlackBoxFuncCall::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { - Acir::BlackBoxFuncCall::BigIntSub obj; - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Acir { - - inline bool operator==(const BlackBoxFuncCall::BigIntMul &lhs, const BlackBoxFuncCall::BigIntMul &rhs) { - if (!(lhs.lhs == rhs.lhs)) { return false; } - if (!(lhs.rhs == rhs.rhs)) { return false; } - if (!(lhs.output == rhs.output)) { return false; } - return true; - } - - inline std::vector BlackBoxFuncCall::BigIntMul::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxFuncCall::BigIntMul BlackBoxFuncCall::BigIntMul::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Acir - -template <> -template -void serde::Serializable::serialize(const Acir::BlackBoxFuncCall::BigIntMul &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); - serde::Serializable::serialize(obj.output, serializer); -} - -template <> -template -Acir::BlackBoxFuncCall::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Acir::BlackBoxFuncCall::BigIntMul obj; - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Acir { - - inline bool operator==(const BlackBoxFuncCall::BigIntDiv &lhs, const BlackBoxFuncCall::BigIntDiv &rhs) { - if (!(lhs.lhs == rhs.lhs)) { return false; } - if (!(lhs.rhs == rhs.rhs)) { return false; } - if (!(lhs.output == rhs.output)) { return false; } - return true; - } - - inline std::vector BlackBoxFuncCall::BigIntDiv::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxFuncCall::BigIntDiv BlackBoxFuncCall::BigIntDiv::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Acir - -template <> -template -void serde::Serializable::serialize(const Acir::BlackBoxFuncCall::BigIntDiv &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); - serde::Serializable::serialize(obj.output, serializer); -} - -template <> -template -Acir::BlackBoxFuncCall::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Acir::BlackBoxFuncCall::BigIntDiv obj; - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Acir { - - inline bool operator==(const BlackBoxFuncCall::BigIntFromLeBytes &lhs, const BlackBoxFuncCall::BigIntFromLeBytes &rhs) { - if (!(lhs.inputs == rhs.inputs)) { return false; } - if (!(lhs.modulus == rhs.modulus)) { return false; } - if (!(lhs.output == rhs.output)) { return false; } - return true; - } - - inline std::vector BlackBoxFuncCall::BigIntFromLeBytes::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxFuncCall::BigIntFromLeBytes BlackBoxFuncCall::BigIntFromLeBytes::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Acir - -template <> -template -void serde::Serializable::serialize(const Acir::BlackBoxFuncCall::BigIntFromLeBytes &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.modulus, serializer); - serde::Serializable::serialize(obj.output, serializer); -} - -template <> -template -Acir::BlackBoxFuncCall::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { - Acir::BlackBoxFuncCall::BigIntFromLeBytes obj; - obj.inputs = serde::Deserializable::deserialize(deserializer); - obj.modulus = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Acir { - - inline bool operator==(const BlackBoxFuncCall::BigIntToLeBytes &lhs, const BlackBoxFuncCall::BigIntToLeBytes &rhs) { - if (!(lhs.input == rhs.input)) { return false; } - if (!(lhs.outputs == rhs.outputs)) { return false; } - return true; - } - - inline std::vector BlackBoxFuncCall::BigIntToLeBytes::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxFuncCall::BigIntToLeBytes BlackBoxFuncCall::BigIntToLeBytes::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Acir - -template <> -template -void serde::Serializable::serialize(const Acir::BlackBoxFuncCall::BigIntToLeBytes &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.input, serializer); - serde::Serializable::serialize(obj.outputs, serializer); -} - -template <> -template -Acir::BlackBoxFuncCall::BigIntToLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { - Acir::BlackBoxFuncCall::BigIntToLeBytes obj; - obj.input = serde::Deserializable::deserialize(deserializer); - obj.outputs = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Acir { - - inline bool operator==(const BlackBoxFuncCall::Poseidon2Permutation &lhs, const BlackBoxFuncCall::Poseidon2Permutation &rhs) { - if (!(lhs.inputs == rhs.inputs)) { return false; } - if (!(lhs.outputs == rhs.outputs)) { return false; } - if (!(lhs.len == rhs.len)) { return false; } - return true; - } - - inline std::vector BlackBoxFuncCall::Poseidon2Permutation::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } @@ -6886,7 +6133,6 @@ template void serde::Serializable::serialize(const Acir::BlackBoxFuncCall::Poseidon2Permutation &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); - serde::Serializable::serialize(obj.len, serializer); } template <> @@ -6895,7 +6141,6 @@ Acir::BlackBoxFuncCall::Poseidon2Permutation serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); - obj.len = serde::Deserializable::deserialize(deserializer); return obj; } @@ -7256,299 +6501,23 @@ Acir::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable BlackBoxOp::MultiScalarMul::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxOp::MultiScalarMul BlackBoxOp::MultiScalarMul::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Acir - -template <> -template -void serde::Serializable::serialize(const Acir::BlackBoxOp::MultiScalarMul &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.points, serializer); - serde::Serializable::serialize(obj.scalars, serializer); - serde::Serializable::serialize(obj.outputs, serializer); -} - -template <> -template -Acir::BlackBoxOp::MultiScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Acir::BlackBoxOp::MultiScalarMul obj; - obj.points = serde::Deserializable::deserialize(deserializer); - obj.scalars = serde::Deserializable::deserialize(deserializer); - obj.outputs = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Acir { - - inline bool operator==(const BlackBoxOp::EmbeddedCurveAdd &lhs, const BlackBoxOp::EmbeddedCurveAdd &rhs) { - if (!(lhs.input1_x == rhs.input1_x)) { return false; } - if (!(lhs.input1_y == rhs.input1_y)) { return false; } - if (!(lhs.input1_infinite == rhs.input1_infinite)) { return false; } - if (!(lhs.input2_x == rhs.input2_x)) { return false; } - if (!(lhs.input2_y == rhs.input2_y)) { return false; } - if (!(lhs.input2_infinite == rhs.input2_infinite)) { return false; } - if (!(lhs.result == rhs.result)) { return false; } - return true; - } - - inline std::vector BlackBoxOp::EmbeddedCurveAdd::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxOp::EmbeddedCurveAdd BlackBoxOp::EmbeddedCurveAdd::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Acir - -template <> -template -void serde::Serializable::serialize(const Acir::BlackBoxOp::EmbeddedCurveAdd &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.input1_x, serializer); - serde::Serializable::serialize(obj.input1_y, serializer); - serde::Serializable::serialize(obj.input1_infinite, serializer); - serde::Serializable::serialize(obj.input2_x, serializer); - serde::Serializable::serialize(obj.input2_y, serializer); - serde::Serializable::serialize(obj.input2_infinite, serializer); - serde::Serializable::serialize(obj.result, serializer); -} - -template <> -template -Acir::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Acir::BlackBoxOp::EmbeddedCurveAdd obj; - obj.input1_x = serde::Deserializable::deserialize(deserializer); - obj.input1_y = serde::Deserializable::deserialize(deserializer); - obj.input1_infinite = serde::Deserializable::deserialize(deserializer); - obj.input2_x = serde::Deserializable::deserialize(deserializer); - obj.input2_y = serde::Deserializable::deserialize(deserializer); - obj.input2_infinite = serde::Deserializable::deserialize(deserializer); - obj.result = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Acir { - - inline bool operator==(const BlackBoxOp::BigIntAdd &lhs, const BlackBoxOp::BigIntAdd &rhs) { - if (!(lhs.lhs == rhs.lhs)) { return false; } - if (!(lhs.rhs == rhs.rhs)) { return false; } - if (!(lhs.output == rhs.output)) { return false; } - return true; - } - - inline std::vector BlackBoxOp::BigIntAdd::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxOp::BigIntAdd BlackBoxOp::BigIntAdd::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Acir - -template <> -template -void serde::Serializable::serialize(const Acir::BlackBoxOp::BigIntAdd &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); - serde::Serializable::serialize(obj.output, serializer); -} - -template <> -template -Acir::BlackBoxOp::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Acir::BlackBoxOp::BigIntAdd obj; - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Acir { - - inline bool operator==(const BlackBoxOp::BigIntSub &lhs, const BlackBoxOp::BigIntSub &rhs) { - if (!(lhs.lhs == rhs.lhs)) { return false; } - if (!(lhs.rhs == rhs.rhs)) { return false; } - if (!(lhs.output == rhs.output)) { return false; } - return true; - } - - inline std::vector BlackBoxOp::BigIntSub::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxOp::BigIntSub BlackBoxOp::BigIntSub::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Acir - -template <> -template -void serde::Serializable::serialize(const Acir::BlackBoxOp::BigIntSub &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); - serde::Serializable::serialize(obj.output, serializer); -} - -template <> -template -Acir::BlackBoxOp::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { - Acir::BlackBoxOp::BigIntSub obj; - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Acir { - - inline bool operator==(const BlackBoxOp::BigIntMul &lhs, const BlackBoxOp::BigIntMul &rhs) { - if (!(lhs.lhs == rhs.lhs)) { return false; } - if (!(lhs.rhs == rhs.rhs)) { return false; } - if (!(lhs.output == rhs.output)) { return false; } - return true; - } - - inline std::vector BlackBoxOp::BigIntMul::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxOp::BigIntMul BlackBoxOp::BigIntMul::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Acir - -template <> -template -void serde::Serializable::serialize(const Acir::BlackBoxOp::BigIntMul &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); - serde::Serializable::serialize(obj.output, serializer); -} - -template <> -template -Acir::BlackBoxOp::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Acir::BlackBoxOp::BigIntMul obj; - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Acir { - - inline bool operator==(const BlackBoxOp::BigIntDiv &lhs, const BlackBoxOp::BigIntDiv &rhs) { - if (!(lhs.lhs == rhs.lhs)) { return false; } - if (!(lhs.rhs == rhs.rhs)) { return false; } - if (!(lhs.output == rhs.output)) { return false; } - return true; - } - - inline std::vector BlackBoxOp::BigIntDiv::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxOp::BigIntDiv BlackBoxOp::BigIntDiv::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Acir - -template <> -template -void serde::Serializable::serialize(const Acir::BlackBoxOp::BigIntDiv &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); - serde::Serializable::serialize(obj.output, serializer); -} - -template <> -template -Acir::BlackBoxOp::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Acir::BlackBoxOp::BigIntDiv obj; - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Acir { - - inline bool operator==(const BlackBoxOp::BigIntFromLeBytes &lhs, const BlackBoxOp::BigIntFromLeBytes &rhs) { - if (!(lhs.inputs == rhs.inputs)) { return false; } - if (!(lhs.modulus == rhs.modulus)) { return false; } - if (!(lhs.output == rhs.output)) { return false; } + + inline bool operator==(const BlackBoxOp::MultiScalarMul &lhs, const BlackBoxOp::MultiScalarMul &rhs) { + if (!(lhs.points == rhs.points)) { return false; } + if (!(lhs.scalars == rhs.scalars)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } return true; } - inline std::vector BlackBoxOp::BigIntFromLeBytes::bincodeSerialize() const { + inline std::vector BlackBoxOp::MultiScalarMul::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline BlackBoxOp::BigIntFromLeBytes BlackBoxOp::BigIntFromLeBytes::bincodeDeserialize(std::vector input) { + inline BlackBoxOp::MultiScalarMul BlackBoxOp::MultiScalarMul::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw_or_abort("Some input bytes were not read"); } @@ -7559,39 +6528,44 @@ namespace Acir { template <> template -void serde::Serializable::serialize(const Acir::BlackBoxOp::BigIntFromLeBytes &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.modulus, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Acir::BlackBoxOp::MultiScalarMul &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.points, serializer); + serde::Serializable::serialize(obj.scalars, serializer); + serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Acir::BlackBoxOp::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { - Acir::BlackBoxOp::BigIntFromLeBytes obj; - obj.inputs = serde::Deserializable::deserialize(deserializer); - obj.modulus = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); +Acir::BlackBoxOp::MultiScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Acir::BlackBoxOp::MultiScalarMul obj; + obj.points = serde::Deserializable::deserialize(deserializer); + obj.scalars = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } namespace Acir { - inline bool operator==(const BlackBoxOp::BigIntToLeBytes &lhs, const BlackBoxOp::BigIntToLeBytes &rhs) { - if (!(lhs.input == rhs.input)) { return false; } - if (!(lhs.output == rhs.output)) { return false; } + inline bool operator==(const BlackBoxOp::EmbeddedCurveAdd &lhs, const BlackBoxOp::EmbeddedCurveAdd &rhs) { + if (!(lhs.input1_x == rhs.input1_x)) { return false; } + if (!(lhs.input1_y == rhs.input1_y)) { return false; } + if (!(lhs.input1_infinite == rhs.input1_infinite)) { return false; } + if (!(lhs.input2_x == rhs.input2_x)) { return false; } + if (!(lhs.input2_y == rhs.input2_y)) { return false; } + if (!(lhs.input2_infinite == rhs.input2_infinite)) { return false; } + if (!(lhs.result == rhs.result)) { return false; } return true; } - inline std::vector BlackBoxOp::BigIntToLeBytes::bincodeSerialize() const { + inline std::vector BlackBoxOp::EmbeddedCurveAdd::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline BlackBoxOp::BigIntToLeBytes BlackBoxOp::BigIntToLeBytes::bincodeDeserialize(std::vector input) { + inline BlackBoxOp::EmbeddedCurveAdd BlackBoxOp::EmbeddedCurveAdd::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw_or_abort("Some input bytes were not read"); } @@ -7602,17 +6576,27 @@ namespace Acir { template <> template -void serde::Serializable::serialize(const Acir::BlackBoxOp::BigIntToLeBytes &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.input, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Acir::BlackBoxOp::EmbeddedCurveAdd &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.input1_x, serializer); + serde::Serializable::serialize(obj.input1_y, serializer); + serde::Serializable::serialize(obj.input1_infinite, serializer); + serde::Serializable::serialize(obj.input2_x, serializer); + serde::Serializable::serialize(obj.input2_y, serializer); + serde::Serializable::serialize(obj.input2_infinite, serializer); + serde::Serializable::serialize(obj.result, serializer); } template <> template -Acir::BlackBoxOp::BigIntToLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { - Acir::BlackBoxOp::BigIntToLeBytes obj; - obj.input = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); +Acir::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Acir::BlackBoxOp::EmbeddedCurveAdd obj; + obj.input1_x = serde::Deserializable::deserialize(deserializer); + obj.input1_y = serde::Deserializable::deserialize(deserializer); + obj.input1_infinite = serde::Deserializable::deserialize(deserializer); + obj.input2_x = serde::Deserializable::deserialize(deserializer); + obj.input2_y = serde::Deserializable::deserialize(deserializer); + obj.input2_infinite = serde::Deserializable::deserialize(deserializer); + obj.result = serde::Deserializable::deserialize(deserializer); return obj; } @@ -7621,7 +6605,6 @@ namespace Acir { inline bool operator==(const BlackBoxOp::Poseidon2Permutation &lhs, const BlackBoxOp::Poseidon2Permutation &rhs) { if (!(lhs.message == rhs.message)) { return false; } if (!(lhs.output == rhs.output)) { return false; } - if (!(lhs.len == rhs.len)) { return false; } return true; } @@ -7647,7 +6630,6 @@ template void serde::Serializable::serialize(const Acir::BlackBoxOp::Poseidon2Permutation &obj, Serializer &serializer) { serde::Serializable::serialize(obj.message, serializer); serde::Serializable::serialize(obj.output, serializer); - serde::Serializable::serialize(obj.len, serializer); } template <> @@ -7656,7 +6638,6 @@ Acir::BlackBoxOp::Poseidon2Permutation serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); - obj.len = serde::Deserializable::deserialize(deserializer); return obj; } @@ -7949,6 +6930,7 @@ Acir::BlockType::ReturnData serde::Deserializable:: namespace Acir { inline bool operator==(const BrilligBytecode &lhs, const BrilligBytecode &rhs) { + if (!(lhs.function_name == rhs.function_name)) { return false; } if (!(lhs.bytecode == rhs.bytecode)) { return false; } return true; } @@ -7974,6 +6956,7 @@ template <> template void serde::Serializable::serialize(const Acir::BrilligBytecode &obj, Serializer &serializer) { serializer.increase_container_depth(); + serde::Serializable::serialize(obj.function_name, serializer); serde::Serializable::serialize(obj.bytecode, serializer); serializer.decrease_container_depth(); } @@ -7983,6 +6966,7 @@ template Acir::BrilligBytecode serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); Acir::BrilligBytecode obj; + obj.function_name = serde::Deserializable::deserialize(deserializer); obj.bytecode = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; @@ -8371,47 +7355,6 @@ Acir::BrilligOpcode::Cast serde::Deserializable::dese return obj; } -namespace Acir { - - inline bool operator==(const BrilligOpcode::JumpIfNot &lhs, const BrilligOpcode::JumpIfNot &rhs) { - if (!(lhs.condition == rhs.condition)) { return false; } - if (!(lhs.location == rhs.location)) { return false; } - return true; - } - - inline std::vector BrilligOpcode::JumpIfNot::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BrilligOpcode::JumpIfNot BrilligOpcode::JumpIfNot::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Acir - -template <> -template -void serde::Serializable::serialize(const Acir::BrilligOpcode::JumpIfNot &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.condition, serializer); - serde::Serializable::serialize(obj.location, serializer); -} - -template <> -template -Acir::BrilligOpcode::JumpIfNot serde::Deserializable::deserialize(Deserializer &deserializer) { - Acir::BrilligOpcode::JumpIfNot obj; - obj.condition = serde::Deserializable::deserialize(deserializer); - obj.location = serde::Deserializable::deserialize(deserializer); - return obj; -} - namespace Acir { inline bool operator==(const BrilligOpcode::JumpIf &lhs, const BrilligOpcode::JumpIf &rhs) { @@ -9151,9 +8094,9 @@ Acir::BrilligOutputs::Array serde::Deserializable:: namespace Acir { inline bool operator==(const Circuit &lhs, const Circuit &rhs) { + if (!(lhs.function_name == rhs.function_name)) { return false; } if (!(lhs.current_witness_index == rhs.current_witness_index)) { return false; } if (!(lhs.opcodes == rhs.opcodes)) { return false; } - if (!(lhs.expression_width == rhs.expression_width)) { return false; } if (!(lhs.private_parameters == rhs.private_parameters)) { return false; } if (!(lhs.public_parameters == rhs.public_parameters)) { return false; } if (!(lhs.return_values == rhs.return_values)) { return false; } @@ -9182,9 +8125,9 @@ template <> template void serde::Serializable::serialize(const Acir::Circuit &obj, Serializer &serializer) { serializer.increase_container_depth(); + serde::Serializable::serialize(obj.function_name, serializer); serde::Serializable::serialize(obj.current_witness_index, serializer); serde::Serializable::serialize(obj.opcodes, serializer); - serde::Serializable::serialize(obj.expression_width, serializer); serde::Serializable::serialize(obj.private_parameters, serializer); serde::Serializable::serialize(obj.public_parameters, serializer); serde::Serializable::serialize(obj.return_values, serializer); @@ -9197,9 +8140,9 @@ template Acir::Circuit serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); Acir::Circuit obj; + obj.function_name = serde::Deserializable::deserialize(deserializer); obj.current_witness_index = serde::Deserializable::deserialize(deserializer); obj.opcodes = serde::Deserializable::deserialize(deserializer); - obj.expression_width = serde::Deserializable::deserialize(deserializer); obj.private_parameters = serde::Deserializable::deserialize(deserializer); obj.public_parameters = serde::Deserializable::deserialize(deserializer); obj.return_values = serde::Deserializable::deserialize(deserializer); @@ -9208,124 +8151,6 @@ Acir::Circuit serde::Deserializable::deserialize(Deserializer &de return obj; } -namespace Acir { - - inline bool operator==(const ConstantOrWitnessEnum &lhs, const ConstantOrWitnessEnum &rhs) { - if (!(lhs.value == rhs.value)) { return false; } - return true; - } - - inline std::vector ConstantOrWitnessEnum::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline ConstantOrWitnessEnum ConstantOrWitnessEnum::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Acir - -template <> -template -void serde::Serializable::serialize(const Acir::ConstantOrWitnessEnum &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); -} - -template <> -template -Acir::ConstantOrWitnessEnum serde::Deserializable::deserialize(Deserializer &deserializer) { - deserializer.increase_container_depth(); - Acir::ConstantOrWitnessEnum obj; - obj.value = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; -} - -namespace Acir { - - inline bool operator==(const ConstantOrWitnessEnum::Constant &lhs, const ConstantOrWitnessEnum::Constant &rhs) { - if (!(lhs.value == rhs.value)) { return false; } - return true; - } - - inline std::vector ConstantOrWitnessEnum::Constant::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline ConstantOrWitnessEnum::Constant ConstantOrWitnessEnum::Constant::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Acir - -template <> -template -void serde::Serializable::serialize(const Acir::ConstantOrWitnessEnum::Constant &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); -} - -template <> -template -Acir::ConstantOrWitnessEnum::Constant serde::Deserializable::deserialize(Deserializer &deserializer) { - Acir::ConstantOrWitnessEnum::Constant obj; - obj.value = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Acir { - - inline bool operator==(const ConstantOrWitnessEnum::Witness &lhs, const ConstantOrWitnessEnum::Witness &rhs) { - if (!(lhs.value == rhs.value)) { return false; } - return true; - } - - inline std::vector ConstantOrWitnessEnum::Witness::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline ConstantOrWitnessEnum::Witness ConstantOrWitnessEnum::Witness::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Acir - -template <> -template -void serde::Serializable::serialize(const Acir::ConstantOrWitnessEnum::Witness &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); -} - -template <> -template -Acir::ConstantOrWitnessEnum::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { - Acir::ConstantOrWitnessEnum::Witness obj; - obj.value = serde::Deserializable::deserialize(deserializer); - return obj; -} - namespace Acir { inline bool operator==(const Expression &lhs, const Expression &rhs) { @@ -9610,8 +8435,7 @@ Acir::ExpressionWidth::Bounded serde::Deserializable template void serde::Serializable::serialize(const Acir::FunctionInput &obj, Serializer &serializer) { serializer.increase_container_depth(); - serde::Serializable::serialize(obj.input, serializer); - serde::Serializable::serialize(obj.num_bits, serializer); + serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); } @@ -9646,12 +8469,87 @@ template Acir::FunctionInput serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); Acir::FunctionInput obj; - obj.input = serde::Deserializable::deserialize(deserializer); - obj.num_bits = serde::Deserializable::deserialize(deserializer); + obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } +namespace Acir { + + inline bool operator==(const FunctionInput::Constant &lhs, const FunctionInput::Constant &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } + + inline std::vector FunctionInput::Constant::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline FunctionInput::Constant FunctionInput::Constant::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw_or_abort("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Acir + +template <> +template +void serde::Serializable::serialize(const Acir::FunctionInput::Constant &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); +} + +template <> +template +Acir::FunctionInput::Constant serde::Deserializable::deserialize(Deserializer &deserializer) { + Acir::FunctionInput::Constant obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Acir { + + inline bool operator==(const FunctionInput::Witness &lhs, const FunctionInput::Witness &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } + + inline std::vector FunctionInput::Witness::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline FunctionInput::Witness FunctionInput::Witness::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw_or_abort("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Acir + +template <> +template +void serde::Serializable::serialize(const Acir::FunctionInput::Witness &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); +} + +template <> +template +Acir::FunctionInput::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { + Acir::FunctionInput::Witness obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; +} + namespace Acir { inline bool operator==(const HeapArray &lhs, const HeapArray &rhs) { @@ -10442,7 +9340,6 @@ namespace Acir { inline bool operator==(const Opcode::MemoryOp &lhs, const Opcode::MemoryOp &rhs) { if (!(lhs.block_id == rhs.block_id)) { return false; } if (!(lhs.op == rhs.op)) { return false; } - if (!(lhs.predicate == rhs.predicate)) { return false; } return true; } @@ -10468,7 +9365,6 @@ template void serde::Serializable::serialize(const Acir::Opcode::MemoryOp &obj, Serializer &serializer) { serde::Serializable::serialize(obj.block_id, serializer); serde::Serializable::serialize(obj.op, serializer); - serde::Serializable::serialize(obj.predicate, serializer); } template <> @@ -10477,7 +9373,6 @@ Acir::Opcode::MemoryOp serde::Deserializable::deserializ Acir::Opcode::MemoryOp obj; obj.block_id = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); - obj.predicate = serde::Deserializable::deserialize(deserializer); return obj; } diff --git a/acvm-repo/acir/codegen/witness.cpp b/acvm-repo/acir/codegen/witness.cpp index f2f1dbc2d85..01825d0acb7 100644 --- a/acvm-repo/acir/codegen/witness.cpp +++ b/acvm-repo/acir/codegen/witness.cpp @@ -73,7 +73,7 @@ namespace Witnesses { }; struct WitnessMap { - std::map value; + std::map> value; friend bool operator==(const WitnessMap&, const WitnessMap&); std::vector bincodeSerialize() const; diff --git a/acvm-repo/acir/src/circuit/black_box_functions.rs b/acvm-repo/acir/src/circuit/black_box_functions.rs index 898dca40183..e394501094b 100644 --- a/acvm-repo/acir/src/circuit/black_box_functions.rs +++ b/acvm-repo/acir/src/circuit/black_box_functions.rs @@ -36,18 +36,6 @@ pub enum BlackBoxFunc { RecursiveAggregation, /// More details can be found at [crate::circuit::opcodes::BlackBoxFuncCall::EmbeddedCurveAdd] EmbeddedCurveAdd, - /// More details can be found at [crate::circuit::opcodes::BlackBoxFuncCall::BigIntAdd] - BigIntAdd, - /// More details can be found at [crate::circuit::opcodes::BlackBoxFuncCall::BigIntSub] - BigIntSub, - /// More details can be found at [crate::circuit::opcodes::BlackBoxFuncCall::BigIntMul] - BigIntMul, - /// More details can be found at [crate::circuit::opcodes::BlackBoxFuncCall::BigIntDiv] - BigIntDiv, - /// More details can be found at [crate::circuit::opcodes::BlackBoxFuncCall::BigIntFromLeBytes] - BigIntFromLeBytes, - /// More details can be found at [crate::circuit::opcodes::BlackBoxFuncCall::BigIntToLeBytes] - BigIntToLeBytes, /// More details can be found at [crate::circuit::opcodes::BlackBoxFuncCall::Poseidon2Permutation] Poseidon2Permutation, /// More details can be found at [crate::circuit::opcodes::BlackBoxFuncCall::Sha256Compression] @@ -75,12 +63,6 @@ impl BlackBoxFunc { BlackBoxFunc::Keccakf1600 => "keccakf1600", BlackBoxFunc::RecursiveAggregation => "recursive_aggregation", BlackBoxFunc::EcdsaSecp256r1 => "ecdsa_secp256r1", - BlackBoxFunc::BigIntAdd => "bigint_add", - BlackBoxFunc::BigIntSub => "bigint_sub", - BlackBoxFunc::BigIntMul => "bigint_mul", - BlackBoxFunc::BigIntDiv => "bigint_div", - BlackBoxFunc::BigIntFromLeBytes => "bigint_from_le_bytes", - BlackBoxFunc::BigIntToLeBytes => "bigint_to_le_bytes", BlackBoxFunc::Poseidon2Permutation => "poseidon2_permutation", BlackBoxFunc::Sha256Compression => "sha256_compression", } @@ -100,12 +82,6 @@ impl BlackBoxFunc { "range" => Some(BlackBoxFunc::RANGE), "keccakf1600" => Some(BlackBoxFunc::Keccakf1600), "recursive_aggregation" => Some(BlackBoxFunc::RecursiveAggregation), - "bigint_add" => Some(BlackBoxFunc::BigIntAdd), - "bigint_sub" => Some(BlackBoxFunc::BigIntSub), - "bigint_mul" => Some(BlackBoxFunc::BigIntMul), - "bigint_div" => Some(BlackBoxFunc::BigIntDiv), - "bigint_from_le_bytes" => Some(BlackBoxFunc::BigIntFromLeBytes), - "bigint_to_le_bytes" => Some(BlackBoxFunc::BigIntToLeBytes), "poseidon2_permutation" => Some(BlackBoxFunc::Poseidon2Permutation), "sha256_compression" => Some(BlackBoxFunc::Sha256Compression), _ => None, @@ -126,12 +102,6 @@ impl BlackBoxFunc { | BlackBoxFunc::EcdsaSecp256k1 | BlackBoxFunc::EcdsaSecp256r1 | BlackBoxFunc::Keccakf1600 - | BlackBoxFunc::BigIntAdd - | BlackBoxFunc::BigIntSub - | BlackBoxFunc::BigIntMul - | BlackBoxFunc::BigIntDiv - | BlackBoxFunc::BigIntFromLeBytes - | BlackBoxFunc::BigIntToLeBytes | BlackBoxFunc::Poseidon2Permutation | BlackBoxFunc::Sha256Compression => false, } diff --git a/acvm-repo/acir/src/circuit/brillig.rs b/acvm-repo/acir/src/circuit/brillig.rs index e626745f25f..9c8b666e7c6 100644 --- a/acvm-repo/acir/src/circuit/brillig.rs +++ b/acvm-repo/acir/src/circuit/brillig.rs @@ -82,6 +82,8 @@ impl std::fmt::Display for BrilligOutputs { #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default, Debug, Hash)] #[cfg_attr(feature = "arb", derive(proptest_derive::Arbitrary))] pub struct BrilligBytecode { + #[serde(default)] // For backwards compatibility + pub function_name: String, pub bytecode: Vec>, } diff --git a/acvm-repo/acir/src/circuit/mod.rs b/acvm-repo/acir/src/circuit/mod.rs index 6c339c9e21f..35b8f7440dd 100644 --- a/acvm-repo/acir/src/circuit/mod.rs +++ b/acvm-repo/acir/src/circuit/mod.rs @@ -54,6 +54,9 @@ pub struct Program { #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default, Hash)] #[cfg_attr(feature = "arb", derive(proptest_derive::Arbitrary))] pub struct Circuit { + /// Name of the function represented by this circuit. + #[serde(default)] // For backwards compatibility + pub function_name: String, /// current_witness_index is the highest witness index in the circuit. The next witness to be added to this circuit /// will take on this value. (The value is cached here as an optimization.) pub current_witness_index: u32, @@ -62,8 +65,6 @@ pub struct Circuit { /// The opcodes should be further converted into a backend-specific circuit representation. /// When initial witness inputs are provided, these opcodes can also be used for generating an execution trace. pub opcodes: Vec>, - /// Maximum width of the [expression][Expression]'s which will be constrained - pub expression_width: ExpressionWidth, /// The set of private inputs to the circuit. pub private_parameters: BTreeSet, @@ -414,30 +415,29 @@ mod tests { Circuit, Compression, Opcode, PublicInputs, opcodes::{BlackBoxFuncCall, FunctionInput}, }; - use crate::{ - circuit::{ExpressionWidth, Program}, - native_types::Witness, - }; + use crate::{circuit::Program, native_types::Witness}; use acir_field::{AcirField, FieldElement}; use serde::{Deserialize, Serialize}; fn and_opcode() -> Opcode { Opcode::BlackBoxFuncCall(BlackBoxFuncCall::AND { - lhs: FunctionInput::witness(Witness(1), 4), - rhs: FunctionInput::witness(Witness(2), 4), + lhs: FunctionInput::Witness(Witness(1)), + rhs: FunctionInput::Witness(Witness(2)), + num_bits: 4, output: Witness(3), }) } fn range_opcode() -> Opcode { Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { - input: FunctionInput::witness(Witness(1), 8), + input: FunctionInput::Witness(Witness(1)), + num_bits: 8, }) } fn keccakf1600_opcode() -> Opcode { let inputs: Box<[FunctionInput; 25]> = - Box::new(std::array::from_fn(|i| FunctionInput::witness(Witness(i as u32 + 1), 8))); + Box::new(std::array::from_fn(|i| FunctionInput::Witness(Witness(i as u32 + 1)))); let outputs: Box<[Witness; 25]> = Box::new(std::array::from_fn(|i| Witness(i as u32 + 26))); Opcode::BlackBoxFuncCall(BlackBoxFuncCall::Keccakf1600 { inputs, outputs }) @@ -446,8 +446,8 @@ mod tests { #[test] fn serialization_roundtrip() { let circuit = Circuit { + function_name: "test".to_string(), current_witness_index: 5, - expression_width: ExpressionWidth::Unbounded, opcodes: vec![and_opcode::(), range_opcode()], private_parameters: BTreeSet::new(), public_parameters: PublicInputs(BTreeSet::from_iter(vec![Witness(2), Witness(12)])), @@ -471,8 +471,8 @@ mod tests { #[test] fn test_serialize() { let circuit = Circuit { + function_name: "test".to_string(), current_witness_index: 0, - expression_width: ExpressionWidth::Unbounded, opcodes: vec![ Opcode::AssertZero(crate::native_types::Expression { mul_terms: vec![], @@ -517,8 +517,8 @@ mod tests { #[test] fn circuit_display_snapshot() { let circuit = Circuit { + function_name: "test".to_string(), current_witness_index: 3, - expression_width: ExpressionWidth::Unbounded, opcodes: vec![ Opcode::AssertZero(crate::native_types::Expression { mul_terms: vec![], @@ -540,15 +540,15 @@ mod tests { insta::assert_snapshot!( circuit.to_string(), @r" - current witness: w3 - private parameters: [] - public parameters: [w2] - return values: [w2] - EXPR [ (2, w1) 8 ] - BLACKBOX::RANGE [(w1, 8)] [] - BLACKBOX::AND [(w1, 4), (w2, 4)] [w3] - BLACKBOX::KECCAKF1600 [(w1, 8), (w2, 8), (w3, 8), (w4, 8), (w5, 8), (w6, 8), (w7, 8), (w8, 8), (w9, 8), (w10, 8), (w11, 8), (w12, 8), (w13, 8), (w14, 8), (w15, 8), (w16, 8), (w17, 8), (w18, 8), (w19, 8), (w20, 8), (w21, 8), (w22, 8), (w23, 8), (w24, 8), (w25, 8)] [w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43, w44, w45, w46, w47, w48, w49, w50] - " + current witness: w3 + private parameters: [] + public parameters: [w2] + return values: [w2] + EXPR [ (2, w1) 8 ] + BLACKBOX::RANGE [w1]:8 bits [] + BLACKBOX::AND [w1, w2]:4 bits [w3] + BLACKBOX::KECCAKF1600 [w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25] [w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43, w44, w45, w46, w47, w48, w49, w50] + " ); } diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index 22a9fddb5ff..f8962bad9bf 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -13,9 +13,7 @@ use serde::{Deserialize, Serialize}; mod black_box_function_call; mod memory_operation; -pub use black_box_function_call::{ - BlackBoxFuncCall, ConstantOrWitnessEnum, FunctionInput, InvalidInputBitSize, -}; +pub use black_box_function_call::{BlackBoxFuncCall, FunctionInput, InvalidInputBitSize}; pub use memory_operation::{BlockId, MemOp}; /// Type for a memory block @@ -102,9 +100,6 @@ pub enum Opcode { block_id: BlockId, /// Describe the memory operation to perform op: MemOp, - /// Predicate of the memory operation - indicates if it should be skipped - /// Disables the execution of the opcode when the expression evaluates to zero - predicate: Option>, }, /// Initialize an ACIR array from a vector of witnesses. @@ -153,11 +148,8 @@ impl std::fmt::Display for Opcode { match self { Opcode::AssertZero(expr) => expr.fmt(f), Opcode::BlackBoxFuncCall(g) => g.fmt(f), - Opcode::MemoryOp { block_id, op, predicate } => { + Opcode::MemoryOp { block_id, op } => { write!(f, "MEM ")?; - if let Some(pred) = predicate { - writeln!(f, "PREDICATE: {pred}")?; - } let is_read = op.operation.is_zero(); if is_read { @@ -249,26 +241,28 @@ mod tests { #[test] fn blackbox_snapshot() { let xor: Opcode = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::XOR { - lhs: FunctionInput::witness(0.into(), 32), - rhs: FunctionInput::witness(1.into(), 32), + lhs: FunctionInput::Witness(0.into()), + rhs: FunctionInput::Witness(1.into()), + num_bits: 32, output: Witness(3), }); insta::assert_snapshot!( xor.to_string(), - @"BLACKBOX::XOR [(w0, 32), (w1, 32)] [w3]" + @"BLACKBOX::XOR [w0, w1]:32 bits [w3]" ); } #[test] fn range_display_snapshot() { let range: Opcode = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { - input: FunctionInput::witness(0.into(), 32), + input: FunctionInput::Witness(0.into()), + num_bits: 32, }); insta::assert_snapshot!( range.to_string(), - @"BLACKBOX::RANGE [(w0, 32)] []" + @"BLACKBOX::RANGE [w0]:32 bits []" ); } } diff --git a/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs b/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs index 75cc1d8d361..06547071044 100644 --- a/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs +++ b/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs @@ -5,8 +5,8 @@ use std::collections::BTreeSet; +use crate::BlackBoxFunc; use crate::native_types::Witness; -use crate::{AcirField, BlackBoxFunc}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use thiserror::Error; @@ -14,51 +14,39 @@ use thiserror::Error; /// Enumeration for black box function inputs #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)] #[cfg_attr(feature = "arb", derive(proptest_derive::Arbitrary))] -pub enum ConstantOrWitnessEnum { +pub enum FunctionInput { /// A constant field element Constant(F), /// A witness element, representing dynamic inputs Witness(Witness), } -/// Input to a black box call -#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)] -#[cfg_attr(feature = "arb", derive(proptest_derive::Arbitrary))] -pub struct FunctionInput { - /// The actual input value - input: ConstantOrWitnessEnum, - /// A constant representing the bit size of the input value - /// Some functions will not use all of the witness - /// So we need to supply how many bits of the witness is needed - num_bits: u32, +impl std::fmt::Display for FunctionInput { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self { + FunctionInput::Constant(constant) => { + write!(f, "{constant}") + } + FunctionInput::Witness(witness) => { + write!(f, "w{}", witness.0) + } + } + } } impl FunctionInput { - pub fn to_witness(&self) -> Witness { - match self.input { - ConstantOrWitnessEnum::Constant(_) => unreachable!("ICE - Expected Witness"), - ConstantOrWitnessEnum::Witness(witness) => witness, + pub fn is_constant(&self) -> bool { + match self { + FunctionInput::Constant(_) => true, + FunctionInput::Witness(_) => false, } } - pub fn input(self) -> ConstantOrWitnessEnum { - self.input - } - - pub fn input_ref(&self) -> &ConstantOrWitnessEnum { - &self.input - } - - pub fn num_bits(&self) -> u32 { - self.num_bits - } - - pub fn witness(witness: Witness, num_bits: u32) -> FunctionInput { - FunctionInput { input: ConstantOrWitnessEnum::Witness(witness), num_bits } - } - - pub fn is_constant(&self) -> bool { - matches!(self.input, ConstantOrWitnessEnum::Constant(_)) + pub fn to_witness(&self) -> Witness { + match self { + FunctionInput::Constant(_) => unreachable!("ICE - Expected Witness"), + FunctionInput::Witness(witness) => *witness, + } } } @@ -70,31 +58,6 @@ pub struct InvalidInputBitSize { pub max_bits: u32, } -impl FunctionInput { - pub fn constant(value: F, max_bits: u32) -> Result, InvalidInputBitSize> { - if value.num_bits() <= max_bits { - Ok(FunctionInput { input: ConstantOrWitnessEnum::Constant(value), num_bits: max_bits }) - } else { - let value_num_bits = value.num_bits(); - let value = format!("{value}"); - Err(InvalidInputBitSize { value, value_num_bits, max_bits }) - } - } -} - -impl std::fmt::Display for FunctionInput { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match &self.input { - ConstantOrWitnessEnum::Constant(constant) => { - write!(f, "({constant}, {})", self.num_bits) - } - ConstantOrWitnessEnum::Witness(witness) => { - write!(f, "({}, {})", witness, self.num_bits) - } - } - } -} - /// These opcodes represent a specialized computation. /// Even if any computation can be done using only assert-zero opcodes, /// it is not always efficient. @@ -120,18 +83,18 @@ pub enum BlackBoxFuncCall { /// - rhs: (witness, bit_size) /// - output: a witness whose value is constrained to be lhs AND rhs, as /// bit_size bit integers - AND { lhs: FunctionInput, rhs: FunctionInput, output: Witness }, + AND { lhs: FunctionInput, rhs: FunctionInput, num_bits: u32, output: Witness }, /// Performs the bitwise XOR of `lhs` and `rhs`. `bit_size` must be the same for /// both inputs. /// - lhs: (witness, bit_size) /// - rhs: (witness, bit_size) /// - output: a witness whose value is constrained to be lhs XOR rhs, as /// bit_size bit integers - XOR { lhs: FunctionInput, rhs: FunctionInput, output: Witness }, + XOR { lhs: FunctionInput, rhs: FunctionInput, num_bits: u32, output: Witness }, /// Range constraint to ensure that a witness /// can be represented in the specified number of bits. /// - input: (witness, bit_size) - RANGE { input: FunctionInput }, + RANGE { input: FunctionInput, num_bits: u32 }, /// Computes the Blake2s hash of the inputs, as specified in /// /// - inputs are a byte array, i.e a vector of (witness, 8) @@ -173,6 +136,7 @@ pub enum BlackBoxFuncCall { )] signature: Box<[FunctionInput; 64]>, hashed_message: Box<[FunctionInput; 32]>, + predicate: FunctionInput, output: Witness, }, /// Verifies a ECDSA signature over the secp256r1 curve. @@ -187,6 +151,7 @@ pub enum BlackBoxFuncCall { )] signature: Box<[FunctionInput; 64]>, hashed_message: Box<[FunctionInput; 32]>, + predicate: FunctionInput, output: Witness, }, /// Multiple scalar multiplication (MSM) with a variable base/input point @@ -208,6 +173,7 @@ pub enum BlackBoxFuncCall { MultiScalarMul { points: Vec>, scalars: Vec>, + predicate: FunctionInput, outputs: (Witness, Witness, Witness), }, /// Addition over the embedded curve on which the witness is defined @@ -222,6 +188,7 @@ pub enum BlackBoxFuncCall { EmbeddedCurveAdd { input1: Box<[FunctionInput; 3]>, input2: Box<[FunctionInput; 3]>, + predicate: FunctionInput, outputs: (Witness, Witness, Witness), }, /// Keccak Permutation function of width 1600 @@ -269,19 +236,9 @@ pub enum BlackBoxFuncCall { /// In order for a backend to construct the correct recursive verifier /// it expects the user to specify a proof type. proof_type: u32, + /// A predicate (true or false) to disable the recursive verification + predicate: FunctionInput, }, - /// BigInt addition - BigIntAdd { lhs: u32, rhs: u32, output: u32 }, - /// BigInt subtraction - BigIntSub { lhs: u32, rhs: u32, output: u32 }, - /// BigInt multiplication - BigIntMul { lhs: u32, rhs: u32, output: u32 }, - /// BigInt division - BigIntDiv { lhs: u32, rhs: u32, output: u32 }, - /// BigInt from le bytes - BigIntFromLeBytes { inputs: Vec>, modulus: Vec, output: u32 }, - /// BigInt to le bytes - BigIntToLeBytes { input: u32, outputs: Vec }, /// Applies the Poseidon2 permutation function to the given state, /// outputting the permuted state. Poseidon2Permutation { @@ -289,9 +246,6 @@ pub enum BlackBoxFuncCall { inputs: Vec>, /// Permuted state outputs: Vec, - /// State length (in number of field elements) - /// It is the length of inputs and outputs vectors - len: u32, }, /// Applies the SHA-256 compression function to the input message /// @@ -325,12 +279,6 @@ impl BlackBoxFuncCall { BlackBoxFuncCall::EmbeddedCurveAdd { .. } => BlackBoxFunc::EmbeddedCurveAdd, BlackBoxFuncCall::Keccakf1600 { .. } => BlackBoxFunc::Keccakf1600, BlackBoxFuncCall::RecursiveAggregation { .. } => BlackBoxFunc::RecursiveAggregation, - BlackBoxFuncCall::BigIntAdd { .. } => BlackBoxFunc::BigIntAdd, - BlackBoxFuncCall::BigIntSub { .. } => BlackBoxFunc::BigIntSub, - BlackBoxFuncCall::BigIntMul { .. } => BlackBoxFunc::BigIntMul, - BlackBoxFuncCall::BigIntDiv { .. } => BlackBoxFunc::BigIntDiv, - BlackBoxFuncCall::BigIntFromLeBytes { .. } => BlackBoxFunc::BigIntFromLeBytes, - BlackBoxFuncCall::BigIntToLeBytes { .. } => BlackBoxFunc::BigIntToLeBytes, BlackBoxFuncCall::Poseidon2Permutation { .. } => BlackBoxFunc::Poseidon2Permutation, BlackBoxFuncCall::Sha256Compression { .. } => BlackBoxFunc::Sha256Compression, } @@ -340,6 +288,15 @@ impl BlackBoxFuncCall { self.get_black_box_func().name() } + pub fn bit_size(&self) -> Option { + match self { + BlackBoxFuncCall::AND { num_bits, .. } + | BlackBoxFuncCall::XOR { num_bits, .. } + | BlackBoxFuncCall::RANGE { num_bits, .. } => Some(*num_bits), + _ => None, + } + } + pub fn get_outputs_vec(&self) -> Vec { match self { BlackBoxFuncCall::Blake2s { outputs, .. } @@ -360,16 +317,9 @@ impl BlackBoxFuncCall { | BlackBoxFuncCall::EmbeddedCurveAdd { outputs, .. } => { vec![outputs.0, outputs.1, outputs.2] } - BlackBoxFuncCall::RANGE { .. } - | BlackBoxFuncCall::RecursiveAggregation { .. } - | BlackBoxFuncCall::BigIntFromLeBytes { .. } - | BlackBoxFuncCall::BigIntAdd { .. } - | BlackBoxFuncCall::BigIntSub { .. } - | BlackBoxFuncCall::BigIntMul { .. } - | BlackBoxFuncCall::BigIntDiv { .. } => { + BlackBoxFuncCall::RANGE { .. } | BlackBoxFuncCall::RecursiveAggregation { .. } => { vec![] } - BlackBoxFuncCall::BigIntToLeBytes { outputs, .. } => outputs.to_vec(), } } } @@ -379,7 +329,6 @@ impl BlackBoxFuncCall { match self { BlackBoxFuncCall::Blake2s { inputs, .. } | BlackBoxFuncCall::Blake3 { inputs, .. } - | BlackBoxFuncCall::BigIntFromLeBytes { inputs, .. } | BlackBoxFuncCall::Poseidon2Permutation { inputs, .. } => inputs.to_vec(), BlackBoxFuncCall::Keccakf1600 { inputs, .. } => inputs.to_vec(), @@ -396,28 +345,26 @@ impl BlackBoxFuncCall { BlackBoxFuncCall::AND { lhs, rhs, .. } | BlackBoxFuncCall::XOR { lhs, rhs, .. } => { vec![*lhs, *rhs] } - BlackBoxFuncCall::BigIntAdd { .. } - | BlackBoxFuncCall::BigIntSub { .. } - | BlackBoxFuncCall::BigIntMul { .. } - | BlackBoxFuncCall::BigIntDiv { .. } - | BlackBoxFuncCall::BigIntToLeBytes { .. } => Vec::new(), - BlackBoxFuncCall::MultiScalarMul { points, scalars, .. } => { + BlackBoxFuncCall::RANGE { input, .. } => vec![*input], + + BlackBoxFuncCall::MultiScalarMul { points, scalars, predicate, .. } => { let mut inputs: Vec> = Vec::with_capacity(points.len() + scalars.len()); inputs.extend(points.iter().copied()); inputs.extend(scalars.iter().copied()); + inputs.push(*predicate); inputs } - BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, .. } => { - vec![input1[0], input1[1], input1[2], input2[0], input2[1], input2[2]] + BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, predicate, .. } => { + vec![input1[0], input1[1], input1[2], input2[0], input2[1], input2[2], *predicate] } - BlackBoxFuncCall::RANGE { input } => vec![*input], BlackBoxFuncCall::EcdsaSecp256k1 { public_key_x, public_key_y, signature, hashed_message, - .. + predicate, + output: _, } => { let mut inputs = Vec::with_capacity( public_key_x.len() @@ -429,6 +376,7 @@ impl BlackBoxFuncCall { inputs.extend(public_key_y.iter().copied()); inputs.extend(signature.iter().copied()); inputs.extend(hashed_message.iter().copied()); + inputs.push(*predicate); inputs } BlackBoxFuncCall::EcdsaSecp256r1 { @@ -436,7 +384,8 @@ impl BlackBoxFuncCall { public_key_y, signature, hashed_message, - .. + predicate, + output: _, } => { let mut inputs = Vec::with_capacity( public_key_x.len() @@ -448,6 +397,7 @@ impl BlackBoxFuncCall { inputs.extend(public_key_y.iter().copied()); inputs.extend(signature.iter().copied()); inputs.extend(hashed_message.iter().copied()); + inputs.push(*predicate); inputs } BlackBoxFuncCall::RecursiveAggregation { @@ -456,12 +406,14 @@ impl BlackBoxFuncCall { public_inputs, key_hash, proof_type: _, + predicate, } => { let mut inputs = Vec::new(); inputs.extend(key.iter().copied()); inputs.extend(proof.iter().copied()); inputs.extend(public_inputs.iter().copied()); inputs.push(*key_hash); + inputs.push(*predicate); inputs } } @@ -470,7 +422,7 @@ impl BlackBoxFuncCall { pub fn get_input_witnesses(&self) -> BTreeSet { let mut result = BTreeSet::new(); for input in self.get_inputs_vec() { - if let ConstantOrWitnessEnum::Witness(w) = input.input() { + if let FunctionInput::Witness(w) = input { result.insert(w); } } @@ -492,7 +444,9 @@ impl std::fmt::Display for BlackBoxFuncCall { .join(", "); write!(f, "[{inputs_str}]")?; - + if let Some(bit_size) = self.bit_size() { + write!(f, ":{bit_size} bits")?; + } write!(f, " ")?; // OUTPUTS @@ -548,7 +502,7 @@ mod tests { fn keccakf1600_opcode() -> Opcode { let inputs: Box<[FunctionInput; 25]> = - Box::new(std::array::from_fn(|i| FunctionInput::witness(Witness(i as u32 + 1), 8))); + Box::new(std::array::from_fn(|i| FunctionInput::Witness(Witness(i as u32 + 1)))); let outputs: Box<[Witness; 25]> = Box::new(std::array::from_fn(|i| Witness(i as u32 + 26))); Opcode::BlackBoxFuncCall(BlackBoxFuncCall::Keccakf1600 { inputs, outputs }) @@ -607,19 +561,38 @@ mod arb { BlackBoxFuncCall::AES128Encrypt { inputs, iv, key, outputs } }); - let case_and = (input.clone(), input.clone(), witness.clone()) - .prop_map(|(lhs, rhs, output)| BlackBoxFuncCall::AND { lhs, rhs, output }); + let case_and = (input_arr_3.clone(), input_arr_8.clone(), witness.clone()).prop_map( + |(lhs, rhs, output)| BlackBoxFuncCall::AND { + lhs: lhs[0], + rhs: rhs[1], + num_bits: 8, + output, + }, + ); - let case_xor = (input.clone(), input.clone(), witness.clone()) - .prop_map(|(lhs, rhs, output)| BlackBoxFuncCall::XOR { lhs, rhs, output }); + let case_xor = (input_arr_3.clone(), input_arr_8.clone(), witness.clone()).prop_map( + |(lhs, rhs, output)| BlackBoxFuncCall::XOR { + lhs: lhs[0], + rhs: rhs[1], + num_bits: 8, + output, + }, + ); - let case_range = input.clone().prop_map(|input| BlackBoxFuncCall::RANGE { input }); + let case_range = witness.clone().prop_map(|witness| BlackBoxFuncCall::RANGE { + input: FunctionInput::Witness(witness), + num_bits: 32, + }); - let case_blake2s = (input_vec.clone(), witness_arr_32.clone()) - .prop_map(|(inputs, outputs)| BlackBoxFuncCall::Blake2s { inputs, outputs }); + let case_blake2s = + (input_arr_8.clone(), witness_arr_32.clone()).prop_map(|(inputs, outputs)| { + BlackBoxFuncCall::Blake2s { inputs: inputs.to_vec(), outputs } + }); - let case_blake3 = (input_vec.clone(), witness_arr_32.clone()) - .prop_map(|(inputs, outputs)| BlackBoxFuncCall::Blake3 { inputs, outputs }); + let case_blake3 = + (input_arr_8.clone(), witness_arr_32.clone()).prop_map(|(inputs, outputs)| { + BlackBoxFuncCall::Blake3 { inputs: inputs.to_vec(), outputs } + }); let case_ecdsa_secp256k1 = ( input_arr_32.clone(), @@ -627,15 +600,17 @@ mod arb { input_arr_64.clone(), input_arr_32.clone(), witness.clone(), + input.clone(), ) .prop_map( - |(public_key_x, public_key_y, signature, hashed_message, output)| { + |(public_key_x, public_key_y, signature, hashed_message, output, predicate)| { BlackBoxFuncCall::EcdsaSecp256k1 { public_key_x, public_key_y, signature, hashed_message, output, + predicate, } }, ); @@ -646,15 +621,17 @@ mod arb { input_arr_64.clone(), input_arr_32.clone(), witness.clone(), + input.clone(), ) .prop_map( - |(public_key_x, public_key_y, signature, hashed_message, output)| { + |(public_key_x, public_key_y, signature, hashed_message, output, predicate)| { BlackBoxFuncCall::EcdsaSecp256r1 { public_key_x, public_key_y, signature, hashed_message, output, + predicate, } }, ); @@ -662,23 +639,35 @@ mod arb { let case_multi_scalar_mul = ( input_vec.clone(), input_vec.clone(), + input.clone(), witness.clone(), witness.clone(), witness.clone(), ) - .prop_map(|(points, scalars, w1, w2, w3)| { - BlackBoxFuncCall::MultiScalarMul { points, scalars, outputs: (w1, w2, w3) } + .prop_map(|(points, scalars, predicate, w1, w2, w3)| { + BlackBoxFuncCall::MultiScalarMul { + points, + scalars, + predicate, + outputs: (w1, w2, w3), + } }); let case_embedded_curve_add = ( input_arr_3.clone(), input_arr_3.clone(), + input.clone(), witness.clone(), witness.clone(), witness.clone(), ) - .prop_map(|(input1, input2, w1, w2, w3)| { - BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, outputs: (w1, w2, w3) } + .prop_map(|(input1, input2, predicate, w1, w2, w3)| { + BlackBoxFuncCall::EmbeddedCurveAdd { + input1, + input2, + predicate, + outputs: (w1, w2, w3), + } }); let case_keccakf1600 = (input_arr_25.clone(), witness_arr_25.clone()) @@ -690,48 +679,24 @@ mod arb { input_vec.clone(), input.clone(), any::(), + input.clone(), ) .prop_map( - |(verification_key, proof, public_inputs, key_hash, proof_type)| { + |(verification_key, proof, public_inputs, key_hash, proof_type, predicate)| { BlackBoxFuncCall::RecursiveAggregation { verification_key, proof, public_inputs, key_hash, proof_type, + predicate, } }, ); - let big_int_args = (any::(), any::(), any::()); - - let case_big_int_add = big_int_args - .prop_map(|(lhs, rhs, output)| BlackBoxFuncCall::BigIntAdd { lhs, rhs, output }); - - let case_big_int_sub = big_int_args - .prop_map(|(lhs, rhs, output)| BlackBoxFuncCall::BigIntSub { lhs, rhs, output }); - - let case_big_int_mul = big_int_args - .prop_map(|(lhs, rhs, output)| BlackBoxFuncCall::BigIntMul { lhs, rhs, output }); - - let case_big_int_div = big_int_args - .prop_map(|(lhs, rhs, output)| BlackBoxFuncCall::BigIntDiv { lhs, rhs, output }); - - let case_big_int_from_le_bytes = (input_vec.clone(), any::>(), any::()) - .prop_map(|(inputs, modulus, output)| BlackBoxFuncCall::BigIntFromLeBytes { - inputs, - modulus, - output, - }); - - let case_big_int_to_le_bytes = (any::(), witness_vec.clone()) - .prop_map(|(input, outputs)| BlackBoxFuncCall::BigIntToLeBytes { input, outputs }); - - let case_poseidon2_permutation = (input_vec.clone(), witness_vec.clone(), any::()) - .prop_map(|(inputs, outputs, len)| BlackBoxFuncCall::Poseidon2Permutation { - inputs, - outputs, - len, + let case_poseidon2_permutation = + (input_vec.clone(), witness_vec.clone()).prop_map(|(inputs, outputs)| { + BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs } }); let case_sha256_compression = (input_arr_16, input_arr_8, witness_arr_8).prop_map( @@ -755,12 +720,6 @@ mod arb { case_embedded_curve_add, case_keccakf1600, case_recursive_aggregation, - case_big_int_add, - case_big_int_sub, - case_big_int_mul, - case_big_int_div, - case_big_int_from_le_bytes, - case_big_int_to_le_bytes, case_poseidon2_permutation, case_sha256_compression, ] diff --git a/acvm-repo/acir/src/lib.rs b/acvm-repo/acir/src/lib.rs index b13b3de119a..16e7a1cd377 100644 --- a/acvm-repo/acir/src/lib.rs +++ b/acvm-repo/acir/src/lib.rs @@ -57,7 +57,7 @@ mod reflection { AssertionPayload, Circuit, ExpressionOrMemory, ExpressionWidth, Opcode, OpcodeLocation, Program, brillig::{BrilligInputs, BrilligOutputs}, - opcodes::{BlackBoxFuncCall, BlockType, ConstantOrWitnessEnum, FunctionInput}, + opcodes::{BlackBoxFuncCall, BlockType, FunctionInput}, }, native_types::{Witness, WitnessMap, WitnessStack}, }; @@ -88,7 +88,7 @@ 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(); tracer.trace_simple_type::>().unwrap(); diff --git a/acvm-repo/acir/src/parser/mod.rs b/acvm-repo/acir/src/parser/mod.rs index 7c0a08f1ae7..0325d7f7c98 100644 --- a/acvm-repo/acir/src/parser/mod.rs +++ b/acvm-repo/acir/src/parser/mod.rs @@ -12,10 +12,7 @@ use crate::{ circuit::{ Circuit, Opcode, Program, PublicInputs, brillig::{BrilligFunctionId, BrilligInputs, BrilligOutputs}, - opcodes::{ - AcirFunctionId, BlackBoxFuncCall, BlockId, BlockType, ConstantOrWitnessEnum, - FunctionInput, MemOp, - }, + opcodes::{AcirFunctionId, BlackBoxFuncCall, BlockId, BlockType, FunctionInput, MemOp}, }, native_types::{Expression, Witness}, }; @@ -347,30 +344,43 @@ impl<'a> Parser<'a> { } BlackBoxFunc::AND => { let inputs = self.parse_blackbox_inputs()?; + let num_bits = self.parse_blackbox_bit_size()?; let outputs = self.parse_witness_vector()?; self.expect_len(&inputs, 2, "AND", false)?; self.expect_len(&outputs, 1, "AND", true)?; - BlackBoxFuncCall::AND { lhs: inputs[0], rhs: inputs[1], output: outputs[0] } + BlackBoxFuncCall::AND { + lhs: inputs[0], + rhs: inputs[1], + num_bits, + output: outputs[0], + } } BlackBoxFunc::XOR => { let inputs = self.parse_blackbox_inputs()?; + let num_bits = self.parse_blackbox_bit_size()?; let outputs = self.parse_witness_vector()?; self.expect_len(&inputs, 2, "XOR", false)?; self.expect_len(&outputs, 1, "XOR", true)?; - BlackBoxFuncCall::XOR { lhs: inputs[0], rhs: inputs[1], output: outputs[0] } + BlackBoxFuncCall::XOR { + lhs: inputs[0], + rhs: inputs[1], + num_bits, + output: outputs[0], + } } BlackBoxFunc::RANGE => { let inputs = self.parse_blackbox_inputs()?; + let num_bits = self.parse_blackbox_bit_size()?; let outputs = self.parse_witness_vector()?; self.expect_len(&inputs, 1, "RANGE", false)?; self.expect_len(&outputs, 0, "RANGE", true)?; - BlackBoxFuncCall::RANGE { input: inputs[0] } + BlackBoxFuncCall::RANGE { input: inputs[0], num_bits } } BlackBoxFunc::Blake2s => { let inputs = self.parse_blackbox_inputs()?; @@ -389,6 +399,7 @@ impl<'a> Parser<'a> { BlackBoxFunc::EcdsaSecp256k1 => { let mut inputs = self.parse_blackbox_inputs()?; + let predicate = self.try_extract_tail::<1, _>(&mut inputs, "predicate")?[0]; let hashed_message = self.try_extract_tail::<32, _>(&mut inputs, "hashed_message")?; let signature = self.try_extract_tail::<64, _>(&mut inputs, "signature")?; @@ -405,11 +416,13 @@ impl<'a> Parser<'a> { signature, hashed_message, output, + predicate, } } BlackBoxFunc::EcdsaSecp256r1 => { let mut inputs = self.parse_blackbox_inputs()?; + let predicate = self.try_extract_tail::<1, _>(&mut inputs, "predicate")?[0]; let hashed_message = self.try_extract_tail::<32, _>(&mut inputs, "hashed_message")?; let signature = self.try_extract_tail::<64, _>(&mut inputs, "signature")?; @@ -426,6 +439,7 @@ impl<'a> Parser<'a> { signature, hashed_message, output, + predicate, } } BlackBoxFunc::MultiScalarMul => todo!(), @@ -443,26 +457,25 @@ impl<'a> Parser<'a> { } BlackBoxFunc::EmbeddedCurveAdd => { let mut inputs = self.parse_blackbox_inputs()?; - + let predicate = self.try_extract_tail::<1, _>(&mut inputs, "predicate")?[0]; let input2 = self.try_extract_tail::<3, _>(&mut inputs, "EC add input2")?; let input1 = self.try_extract_tail::<3, _>(&mut inputs, "EC add input1")?; - let outputs = self.parse_witness_vector()?; self.expect_len(&outputs, 3, "EmbeddedCurveAdd", true)?; BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, + predicate, outputs: (outputs[0], outputs[1], outputs[2]), } } BlackBoxFunc::Poseidon2Permutation => { let inputs = self.parse_blackbox_inputs()?; - let len = inputs.len() as u32; let outputs = self.parse_witness_vector()?; - BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs, len } + BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs } } BlackBoxFunc::Sha256Compression => { let mut inputs = self.parse_blackbox_inputs()?; @@ -476,14 +489,6 @@ impl<'a> Parser<'a> { BlackBoxFuncCall::Sha256Compression { inputs, hash_values, outputs } } - BlackBoxFunc::BigIntAdd - | BlackBoxFunc::BigIntSub - | BlackBoxFunc::BigIntMul - | BlackBoxFunc::BigIntDiv - | BlackBoxFunc::BigIntFromLeBytes - | BlackBoxFunc::BigIntToLeBytes => { - unreachable!("Set to be removed, thus they are not implemented") - } }; Ok(func) } @@ -494,18 +499,16 @@ impl<'a> Parser<'a> { let mut inputs = Vec::new(); while !self.eat(Token::RightBracket)? { - self.eat_or_error(Token::LeftParen)?; - let input = match self.token.token() { Token::Int(value) => { let value = *value; self.bump()?; - ConstantOrWitnessEnum::Constant(value) + FunctionInput::Constant(value) } Token::Witness(index) => { let witness = *index; self.bump()?; - ConstantOrWitnessEnum::Witness(Witness(witness)) + FunctionInput::Witness(Witness(witness)) } other => { return Err(ParserError::ExpectedOneOfTokens { @@ -516,26 +519,7 @@ impl<'a> Parser<'a> { } }; - self.eat_or_error(Token::Comma)?; - - let num_bits = self.eat_u32_or_error()?; - - let function_input = match input { - ConstantOrWitnessEnum::Constant(value) => FunctionInput::constant(value, num_bits) - .map_err(|err| ParserError::InvalidInputBitSize { - value: err.value, - value_num_bits: err.value_num_bits, - max_bits: err.max_bits, - span: self.token.span(), - })?, - ConstantOrWitnessEnum::Witness(witness) => { - FunctionInput::witness(witness, num_bits) - } - }; - - inputs.push(function_input); - - self.eat_or_error(Token::RightParen)?; + inputs.push(input); // Eat a comma if there is another input, but do not error if there is no comma // as this means we have reached the end of the inputs. @@ -545,11 +529,16 @@ impl<'a> Parser<'a> { Ok(inputs) } + fn parse_blackbox_bit_size(&mut self) -> ParseResult { + self.eat_or_error(Token::Colon)?; + let num_bits = self.eat_u32_or_error()?; + self.eat_expected_ident("bits")?; + Ok(num_bits) + } + fn parse_memory_op(&mut self) -> ParseResult> { self.eat_keyword_or_error(Keyword::MemoryOp)?; - let predicate = self.eat_predicate()?; - self.eat_or_error(Token::LeftParen)?; // Parse `id: ` @@ -595,11 +584,7 @@ impl<'a> Parser<'a> { self.eat_or_error(Token::RightParen)?; - Ok(Opcode::MemoryOp { - block_id: BlockId(block_id), - op: MemOp { index, value, operation }, - predicate, - }) + Ok(Opcode::MemoryOp { block_id: BlockId(block_id), op: MemOp { index, value, operation } }) } fn parse_memory_init(&mut self) -> ParseResult> { @@ -1037,10 +1022,6 @@ pub(crate) enum ParserError { ExpectedBlackBoxFuncName { found: Token, span: Span }, #[error("Number does not fit in u32, got: '{number}'")] IntegerLargerThanU32 { number: FieldElement, span: Span }, - #[error( - "FunctionInput value has too many bits: value: {value}, {value_num_bits} >= {max_bits}" - )] - InvalidInputBitSize { value: String, value_num_bits: u32, max_bits: u32, span: Span }, #[error("Expected {expected} inputs for {name}, found {found}")] IncorrectInputLength { expected: usize, found: usize, name: String, span: Span }, #[error("Expected {expected} outputs for {name}, found {found}")] @@ -1065,7 +1046,6 @@ impl ParserError { | MissingConstantTerm { span } | ExpectedBlackBoxFuncName { span, .. } | IntegerLargerThanU32 { span, .. } - | InvalidInputBitSize { span, .. } | IncorrectInputLength { span, .. } | IncorrectOutputLength { span, .. } | InitLengthMismatch { span, .. } diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index b4a9ebfc1d4..d6a13336af2 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -128,15 +128,27 @@ fn assert_zero_with_mul_terms() { } #[test] -fn range_and_xor() { +fn range_check() { + let src = " + current witness: w5 + private parameters: [] + public parameters: [] + return values: [] + BLACKBOX::RANGE [w0]:32 bits [] + "; + assert_circuit_roundtrip(src); +} + +#[test] +fn xor() { let src = " current witness: w2 private parameters: [w0] public parameters: [w1] return values: [] - BLACKBOX::RANGE [(w0, 32)] [] - BLACKBOX::RANGE [(w1, 32)] [] - BLACKBOX::XOR [(w0, 32), (w1, 32)] [w2] + BLACKBOX::RANGE [w0]:32 bits [] + BLACKBOX::RANGE [w1]:32 bits [] + BLACKBOX::XOR [w0, w1]:32 bits [w2] EXPR [ (1, w2) -15 ] "; assert_circuit_roundtrip(src); @@ -150,67 +162,67 @@ fn aes128_encrypt() { private parameters: [w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25, w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43] public parameters: [w44, w45, w46, w47, w48, w49, w50, w51, w52, w53, w54, w55, w56, w57, w58, w59] return values: [] - BLACKBOX::RANGE [(w0, 8)] [] - BLACKBOX::RANGE [(w1, 8)] [] - BLACKBOX::RANGE [(w2, 8)] [] - BLACKBOX::RANGE [(w3, 8)] [] - BLACKBOX::RANGE [(w4, 8)] [] - BLACKBOX::RANGE [(w5, 8)] [] - BLACKBOX::RANGE [(w6, 8)] [] - BLACKBOX::RANGE [(w7, 8)] [] - BLACKBOX::RANGE [(w8, 8)] [] - BLACKBOX::RANGE [(w9, 8)] [] - BLACKBOX::RANGE [(w10, 8)] [] - BLACKBOX::RANGE [(w11, 8)] [] - BLACKBOX::RANGE [(w12, 8)] [] - BLACKBOX::RANGE [(w13, 8)] [] - BLACKBOX::RANGE [(w14, 8)] [] - BLACKBOX::RANGE [(w15, 8)] [] - BLACKBOX::RANGE [(w16, 8)] [] - BLACKBOX::RANGE [(w17, 8)] [] - BLACKBOX::RANGE [(w18, 8)] [] - BLACKBOX::RANGE [(w19, 8)] [] - BLACKBOX::RANGE [(w20, 8)] [] - BLACKBOX::RANGE [(w21, 8)] [] - BLACKBOX::RANGE [(w22, 8)] [] - BLACKBOX::RANGE [(w23, 8)] [] - BLACKBOX::RANGE [(w24, 8)] [] - BLACKBOX::RANGE [(w25, 8)] [] - BLACKBOX::RANGE [(w26, 8)] [] - BLACKBOX::RANGE [(w27, 8)] [] - BLACKBOX::RANGE [(w28, 8)] [] - BLACKBOX::RANGE [(w29, 8)] [] - BLACKBOX::RANGE [(w30, 8)] [] - BLACKBOX::RANGE [(w31, 8)] [] - BLACKBOX::RANGE [(w32, 8)] [] - BLACKBOX::RANGE [(w33, 8)] [] - BLACKBOX::RANGE [(w34, 8)] [] - BLACKBOX::RANGE [(w35, 8)] [] - BLACKBOX::RANGE [(w36, 8)] [] - BLACKBOX::RANGE [(w37, 8)] [] - BLACKBOX::RANGE [(w38, 8)] [] - BLACKBOX::RANGE [(w39, 8)] [] - BLACKBOX::RANGE [(w40, 8)] [] - BLACKBOX::RANGE [(w41, 8)] [] - BLACKBOX::RANGE [(w42, 8)] [] - BLACKBOX::RANGE [(w43, 8)] [] - BLACKBOX::RANGE [(w44, 8)] [] - BLACKBOX::RANGE [(w45, 8)] [] - BLACKBOX::RANGE [(w46, 8)] [] - BLACKBOX::RANGE [(w47, 8)] [] - BLACKBOX::RANGE [(w48, 8)] [] - BLACKBOX::RANGE [(w49, 8)] [] - BLACKBOX::RANGE [(w50, 8)] [] - BLACKBOX::RANGE [(w51, 8)] [] - BLACKBOX::RANGE [(w52, 8)] [] - BLACKBOX::RANGE [(w53, 8)] [] - BLACKBOX::RANGE [(w54, 8)] [] - BLACKBOX::RANGE [(w55, 8)] [] - BLACKBOX::RANGE [(w56, 8)] [] - BLACKBOX::RANGE [(w57, 8)] [] - BLACKBOX::RANGE [(w58, 8)] [] - BLACKBOX::RANGE [(w59, 8)] [] - BLACKBOX::AES128_ENCRYPT [(w12, 8), (w13, 8), (w14, 8), (w15, 8), (w16, 8), (w17, 8), (w18, 8), (w19, 8), (w20, 8), (w21, 8), (w22, 8), (w23, 8), (w24, 8), (w25, 8), (w26, 8), (w27, 8), (w28, 8), (w29, 8), (w30, 8), (w31, 8), (w32, 8), (w33, 8), (w34, 8), (w35, 8), (w36, 8), (w37, 8), (w38, 8), (w39, 8), (w40, 8), (w41, 8), (w42, 8), (w43, 8)] [w60, w61, w62, w63, w64, w65, w66, w67, w68, w69, w70, w71, w72, w73, w74, w75] + BLACKBOX::RANGE [w0]:8 bits [] + BLACKBOX::RANGE [w1]:8 bits [] + BLACKBOX::RANGE [w2]:8 bits [] + BLACKBOX::RANGE [w3]:8 bits [] + BLACKBOX::RANGE [w4]:8 bits [] + BLACKBOX::RANGE [w5]:8 bits [] + BLACKBOX::RANGE [w6]:8 bits [] + BLACKBOX::RANGE [w7]:8 bits [] + BLACKBOX::RANGE [w8]:8 bits [] + BLACKBOX::RANGE [w9]:8 bits [] + BLACKBOX::RANGE [w10]:8 bits [] + BLACKBOX::RANGE [w11]:8 bits [] + BLACKBOX::RANGE [w12]:8 bits [] + BLACKBOX::RANGE [w13]:8 bits [] + BLACKBOX::RANGE [w14]:8 bits [] + BLACKBOX::RANGE [w15]:8 bits [] + BLACKBOX::RANGE [w16]:8 bits [] + BLACKBOX::RANGE [w17]:8 bits [] + BLACKBOX::RANGE [w18]:8 bits [] + BLACKBOX::RANGE [w19]:8 bits [] + BLACKBOX::RANGE [w20]:8 bits [] + BLACKBOX::RANGE [w21]:8 bits [] + BLACKBOX::RANGE [w22]:8 bits [] + BLACKBOX::RANGE [w23]:8 bits [] + BLACKBOX::RANGE [w24]:8 bits [] + BLACKBOX::RANGE [w25]:8 bits [] + BLACKBOX::RANGE [w26]:8 bits [] + BLACKBOX::RANGE [w27]:8 bits [] + BLACKBOX::RANGE [w28]:8 bits [] + BLACKBOX::RANGE [w29]:8 bits [] + BLACKBOX::RANGE [w30]:8 bits [] + BLACKBOX::RANGE [w31]:8 bits [] + BLACKBOX::RANGE [w32]:8 bits [] + BLACKBOX::RANGE [w33]:8 bits [] + BLACKBOX::RANGE [w34]:8 bits [] + BLACKBOX::RANGE [w35]:8 bits [] + BLACKBOX::RANGE [w36]:8 bits [] + BLACKBOX::RANGE [w37]:8 bits [] + BLACKBOX::RANGE [w38]:8 bits [] + BLACKBOX::RANGE [w39]:8 bits [] + BLACKBOX::RANGE [w40]:8 bits [] + BLACKBOX::RANGE [w41]:8 bits [] + BLACKBOX::RANGE [w42]:8 bits [] + BLACKBOX::RANGE [w43]:8 bits [] + BLACKBOX::RANGE [w44]:8 bits [] + BLACKBOX::RANGE [w45]:8 bits [] + BLACKBOX::RANGE [w46]:8 bits [] + BLACKBOX::RANGE [w47]:8 bits [] + BLACKBOX::RANGE [w48]:8 bits [] + BLACKBOX::RANGE [w49]:8 bits [] + BLACKBOX::RANGE [w50]:8 bits [] + BLACKBOX::RANGE [w51]:8 bits [] + BLACKBOX::RANGE [w52]:8 bits [] + BLACKBOX::RANGE [w53]:8 bits [] + BLACKBOX::RANGE [w54]:8 bits [] + BLACKBOX::RANGE [w55]:8 bits [] + BLACKBOX::RANGE [w56]:8 bits [] + BLACKBOX::RANGE [w57]:8 bits [] + BLACKBOX::RANGE [w58]:8 bits [] + BLACKBOX::RANGE [w59]:8 bits [] + BLACKBOX::AES128_ENCRYPT [w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25, w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43] [w60, w61, w62, w63, w64, w65, w66, w67, w68, w69, w70, w71, w72, w73, w74, w75] EXPR [ (-1, w44) (1, w60) 0 ] EXPR [ (-1, w45) (1, w61) 0 ] EXPR [ (-1, w46) (1, w62) 0 ] @@ -238,7 +250,7 @@ fn blake2s() { private parameters: [w0, w1, w2, w3, w4] public parameters: [w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25, w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36] return values: [] - BLACKBOX::BLAKE2S [(w0, 8), (w1, 8), (w2, 8), (w3, 8), (w4, 8)] [w37, w38, w39, w40, w41, w42, w43, w44, w45, w46, w47, w48, w49, w50, w51, w52, w53, w54, w55, w56, w57, w58, w59, w60, w61, w62, w63, w64, w65, w66, w67, w68] + BLACKBOX::BLAKE2S [w0, w1, w2, w3, w4] [w37, w38, w39, w40, w41, w42, w43, w44, w45, w46, w47, w48, w49, w50, w51, w52, w53, w54, w55, w56, w57, w58, w59, w60, w61, w62, w63, w64, w65, w66, w67, w68] "; assert_circuit_roundtrip(src); } @@ -250,32 +262,32 @@ fn blake3() { private parameters: [w0, w1, w2, w3, w4] public parameters: [] return values: [] - BLACKBOX::BLAKE3 [(w0, 8), (w1, 8), (w2, 8), (w3, 8), (w4, 8)] [w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25, w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36] + BLACKBOX::BLAKE3 [w0, w1, w2, w3, w4] [w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25, w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36] "; assert_circuit_roundtrip(src); } #[test] fn ecdsa_secp256k1() { - let input_witnesses: Vec = (0..160).map(|i| format!("(w{i}, 8)")).collect(); + let input_witnesses: Vec = (0..161).map(|i| format!("w{i}")).collect(); let inputs_str = input_witnesses.join(", "); let src = format!( " - current witness: w160 + current witness: w161 private parameters: [] public parameters: [] return values: [] - BLACKBOX::ECDSA_SECP256K1 [{inputs_str}] [w160] + BLACKBOX::ECDSA_SECP256K1 [{inputs_str}] [w161] " ); assert_circuit_roundtrip(&src); } #[test] -#[should_panic] +#[should_panic = "Expected 32 inputs for public_key_y, found 3"] fn ecdsa_secp256k1_missing_inputs() { - let input_witnesses: Vec = (0..100).map(|i| format!("(w{i}, 8)")).collect(); + let input_witnesses: Vec = (0..100).map(|i| format!("w{i}")).collect(); let inputs_str = input_witnesses.join(", "); let src = format!( @@ -292,25 +304,25 @@ fn ecdsa_secp256k1_missing_inputs() { #[test] fn ecdsa_secp256r1() { - let input_witnesses: Vec = (0..160).map(|i| format!("(w{i}, 8)")).collect(); + let input_witnesses: Vec = (0..161).map(|i| format!("w{i}")).collect(); let inputs_str = input_witnesses.join(", "); let src = format!( " - current witness: w160 + current witness: w161 private parameters: [] public parameters: [] return values: [] - BLACKBOX::ECDSA_SECP256R1 [{inputs_str}] [w160] + BLACKBOX::ECDSA_SECP256R1 [{inputs_str}] [w161] " ); assert_circuit_roundtrip(&src); } #[test] -#[should_panic] +#[should_panic = "Expected 32 inputs for public_key_y, found 3"] fn ecdsa_secp256r1_missing_inputs() { - let input_witnesses: Vec = (0..100).map(|i| format!("(w{i}, 8)")).collect(); + let input_witnesses: Vec = (0..100).map(|i| format!("w{i}")).collect(); let inputs_str = input_witnesses.join(", "); let src = format!( @@ -327,7 +339,7 @@ fn ecdsa_secp256r1_missing_inputs() { #[test] fn keccakf1600() { - let input_witnesses: Vec = (0..25).map(|i| format!("(w{i}, 64)")).collect(); + let input_witnesses: Vec = (0..25).map(|i| format!("w{i}")).collect(); let inputs_str = input_witnesses.join(", "); let output_witnesses: Vec = (25..50).map(|i| format!("w{i}")).collect(); @@ -346,9 +358,9 @@ fn keccakf1600() { } #[test] -#[should_panic] +#[should_panic = "Expected 25 inputs for Keccakf1600 inputs, found 24"] fn keccakf1600_missing_inputs() { - let input_witnesses: Vec = (0..24).map(|i| format!("(w{i}, 64)")).collect(); + let input_witnesses: Vec = (0..24).map(|i| format!("w{i}")).collect(); let inputs_str = input_witnesses.join(", "); let output_witnesses: Vec = (24..49).map(|i| format!("w{i}")).collect(); @@ -373,7 +385,7 @@ fn embedded_curve_add() { private parameters: [] public parameters: [] return values: [] - BLACKBOX::EMBEDDED_CURVE_ADD [(w0, 255), (w1, 255), (w2, 1), (w3, 255), (w4, 255), (w5, 1)] [w6, w7, w8] + BLACKBOX::EMBEDDED_CURVE_ADD [w0, w1, w2, w3, w4, w5, w6] [w7, w8, w9] "; assert_circuit_roundtrip(src); } @@ -382,11 +394,11 @@ fn embedded_curve_add() { #[should_panic] fn embedded_curve_add_wrong_output_count() { let src = " - current witness: w8 + current witness: w9 private parameters: [] public parameters: [] return values: [] - BLACKBOX::EMBEDDED_CURVE_ADD [(w0, 255), (w1, 255), (w2, 1), (w3, 255), (w4, 255), (w5, 1)] [w6, w7] + BLACKBOX::EMBEDDED_CURVE_ADD [w0, w1, w2, w3, w4, w5, w6] [w7, w8] "; let _ = Circuit::from_str(src).unwrap(); } @@ -398,14 +410,14 @@ fn poseidon2_permutation() { private parameters: [] public parameters: [] return values: [] - BLACKBOX::POSEIDON2_PERMUTATION [(w0, 255), (w1, 255), (w2, 255)] [w3, w4, w5] + BLACKBOX::POSEIDON2_PERMUTATION [w0, w1, w2] [w3, w4, w5] "; assert_circuit_roundtrip(src); } #[test] fn sha256_compression() { - let input_witnesses: Vec = (0..24).map(|i| format!("(w{i}, 8)")).collect(); + let input_witnesses: Vec = (0..24).map(|i| format!("w{i}")).collect(); let inputs_str = input_witnesses.join(", "); let output_witnesses: Vec = (24..32).map(|i| format!("w{i}")).collect(); @@ -426,7 +438,7 @@ fn sha256_compression() { #[test] #[should_panic] fn sha256_compression_missing_outputs() { - let input_witnesses: Vec = (0..24).map(|i| format!("(w{i}, 8)")).collect(); + let input_witnesses: Vec = (0..24).map(|i| format!("w{i}")).collect(); let inputs_str = input_witnesses.join(", "); let output_witnesses: Vec = (24..31).map(|i| format!("w{i}")).collect(); // should be 8 total @@ -456,19 +468,6 @@ fn memory_read() { assert_circuit_roundtrip(src); } -#[test] -fn memory_read_with_predicate() { - let src = " - current witness: w2 - private parameters: [] - public parameters: [] - return values: [] - MEM PREDICATE: EXPR [ (1, w0) 0 ] - (id: 0, read at: EXPR [ (1, w1) 0 ], value: EXPR [ (1, w2) 0 ]) - "; - assert_circuit_roundtrip(src); -} - #[test] fn memory_write() { let src = " @@ -592,25 +591,25 @@ fn array_dynamic() { private parameters: [w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15, w16, w17, w18] public parameters: [] return values: [] - BLACKBOX::RANGE [(w0, 32)] [] - BLACKBOX::RANGE [(w1, 32)] [] - BLACKBOX::RANGE [(w2, 32)] [] - BLACKBOX::RANGE [(w3, 32)] [] - BLACKBOX::RANGE [(w4, 32)] [] + BLACKBOX::RANGE [w0]:32 bits [] + BLACKBOX::RANGE [w1]:32 bits [] + BLACKBOX::RANGE [w2]:32 bits [] + BLACKBOX::RANGE [w3]:32 bits [] + BLACKBOX::RANGE [w4]:32 bits [] INIT (id: 0, len: 5, witnesses: [w0, w1, w2, w3, w4]) - BLACKBOX::RANGE [(w5, 32)] [] - BLACKBOX::RANGE [(w6, 32)] [] + BLACKBOX::RANGE [w5]:32 bits [] + BLACKBOX::RANGE [w6]:32 bits [] INIT (id: 1, len: 5, witnesses: [w7, w8, w9, w10, w11]) - BLACKBOX::RANGE [(w12, 32)] [] - BLACKBOX::RANGE [(w13, 32)] [] - BLACKBOX::RANGE [(w14, 32)] [] - BLACKBOX::RANGE [(w15, 32)] [] - BLACKBOX::RANGE [(w16, 32)] [] - BLACKBOX::RANGE [(w17, 32)] [] + BLACKBOX::RANGE [w12]:32 bits [] + BLACKBOX::RANGE [w13]:32 bits [] + BLACKBOX::RANGE [w14]:32 bits [] + BLACKBOX::RANGE [w15]:32 bits [] + BLACKBOX::RANGE [w16]:32 bits [] + BLACKBOX::RANGE [w17]:32 bits [] EXPR [ (5, w6) (-1, w19) 0 ] - BLACKBOX::RANGE [(w19, 32)] [] + BLACKBOX::RANGE [w19]:32 bits [] EXPR [ (1, w5) (-1, w19) (-1, w20) 0 ] - BLACKBOX::RANGE [(w20, 32)] [] + BLACKBOX::RANGE [w20]:32 bits [] EXPR [ (1, w20) (-1, w21) -5 ] EXPR [ (1, w21) (-1, w22) -3 ] MEM (id: 0, read at: EXPR [ (1, w21) 0 ], value: EXPR [ (1, w23) 0 ]) @@ -618,7 +617,7 @@ fn array_dynamic() { MEM (id: 0, read at: EXPR [ (1, w22) 0 ], value: EXPR [ (1, w24) 0 ]) EXPR [ (1, w24) -101 ] BRILLIG CALL func 0: inputs: [EXPR [ (1, w22) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w25, w26] - BLACKBOX::RANGE [(w26, 32)] [] + BLACKBOX::RANGE [w26]:32 bits [] EXPR [ (1, w22) (-4294967296, w25) (-1, w26) 4294967291 ] EXPR [ (-1, w25) 0 ] EXPR [ (-1, w27) 0 ] @@ -629,16 +628,16 @@ fn array_dynamic() { MEM (id: 0, read at: EXPR [ (1, w29) 0 ], value: EXPR [ (1, w30) 0 ]) EXPR [ (1, w30) 0 ] BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967286 ], EXPR [ 4294967296 ]], outputs: [w31, w32] - BLACKBOX::RANGE [(w31, 1)] [] - BLACKBOX::RANGE [(w32, 32)] [] + BLACKBOX::RANGE [w31]:1 bits [] + BLACKBOX::RANGE [w32]:32 bits [] EXPR [ (1, w21) (-4294967296, w31) (-1, w32) 4294967286 ] EXPR [ (-1, w21, w31) (1, w21) (-1, w33) 0 ] MEM (id: 0, read at: EXPR [ (1, w33) 0 ], value: EXPR [ (1, w34) 0 ]) EXPR [ (-1, w31, w34) (2, w31) (1, w34) (-1, w35) -2 ] - BLACKBOX::RANGE [(w35, 32)] [] + BLACKBOX::RANGE [w35]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w36, w37] - BLACKBOX::RANGE [(w36, 1)] [] - BLACKBOX::RANGE [(w37, 32)] [] + BLACKBOX::RANGE [w36]:1 bits [] + BLACKBOX::RANGE [w37]:32 bits [] EXPR [ (1, w21) (-4294967296, w36) (-1, w37) 4294967291 ] EXPR [ (1, w31, w36) (-1, w36) 0 ] EXPR [ (-1, w21, w31) (1, w21) (-1, w38) 0 ] @@ -679,22 +678,22 @@ fn array_dynamic() { BRILLIG CALL func 1: inputs: [EXPR [ (1, w62) (1, w63) (1, w64) (1, w65) (1, w66) 0 ]], outputs: [w67] EXPR [ (1, w62, w67) (1, w63, w67) (1, w64, w67) (1, w65, w67) (1, w66, w67) -1 ] BRILLIG CALL func 0: inputs: [EXPR [ (1, w18) 0 ], EXPR [ 4294967296 ]], outputs: [w68, w69] - BLACKBOX::RANGE [(w68, 222)] [] - BLACKBOX::RANGE [(w69, 32)] [] + BLACKBOX::RANGE [w68]:222 bits [] + BLACKBOX::RANGE [w69]:32 bits [] EXPR [ (1, w18) (-4294967296, w68) (-1, w69) 0 ] EXPR [ (-1, w68) (-1, w70) 5096253676302562286669017222071363378443840053029366383258766538131 ] - BLACKBOX::RANGE [(w70, 222)] [] + BLACKBOX::RANGE [w70]:222 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (-1, w68) 5096253676302562286669017222071363378443840053029366383258766538131 ]], outputs: [w71] EXPR [ (-1, w68, w71) (5096253676302562286669017222071363378443840053029366383258766538131, w71) (1, w72) -1 ] EXPR [ (-1, w68, w72) (5096253676302562286669017222071363378443840053029366383258766538131, w72) 0 ] EXPR [ (1, w69, w72) (268435455, w72) (-1, w73) 0 ] - BLACKBOX::RANGE [(w73, 32)] [] + BLACKBOX::RANGE [w73]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (-1, w69) 4294967299 ], EXPR [ 4294967296 ]], outputs: [w74, w75] - BLACKBOX::RANGE [(w74, 1)] [] - BLACKBOX::RANGE [(w75, 32)] [] + BLACKBOX::RANGE [w74]:1 bits [] + BLACKBOX::RANGE [w75]:32 bits [] EXPR [ (-1, w69) (-4294967296, w74) (-1, w75) 4294967299 ] EXPR [ (-1, w17, w74) (1, w17) (-3, w74) (-1, w76) 3 ] - BLACKBOX::RANGE [(w76, 32)] [] + BLACKBOX::RANGE [w76]:32 bits [] EXPR [ (-1, w74, w76) (1, w76) (-1, w77) 0 ] MEM (id: 1, read at: EXPR [ (1, w77) 0 ], value: EXPR [ (1, w78) 0 ]) EXPR [ (1, w15, w74) (-1, w74, w78) (-1, w15) (1, w78) 0 ] @@ -740,7 +739,7 @@ fn fold_basic_mismatched_ids() { current witness: w3 private parameters: [w0, w1] public parameters: [] - return value indices : [w2] + return values: [w2] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] EXPR [ (1, w0, w3) (-1, w1, w3) -1 ] EXPR [ (-1, w0) (1, w2) 0 ] diff --git a/acvm-repo/acir/src/proto/acir/circuit.proto b/acvm-repo/acir/src/proto/acir/circuit.proto index c0981d6e30c..2e9878ab646 100644 --- a/acvm-repo/acir/src/proto/acir/circuit.proto +++ b/acvm-repo/acir/src/proto/acir/circuit.proto @@ -7,11 +7,11 @@ import "acir/native.proto"; message Circuit { uint32 current_witness_index = 1; repeated Opcode opcodes = 2; - ExpressionWidth expression_width = 3; - repeated native.Witness private_parameters = 4; - repeated native.Witness public_parameters = 5; - repeated native.Witness return_values = 6; - repeated AssertMessage assert_messages = 7; + repeated native.Witness private_parameters = 3; + repeated native.Witness public_parameters = 4; + repeated native.Witness return_values = 5; + repeated AssertMessage assert_messages = 6; + string function_name = 7; } message ExpressionWidth { @@ -63,7 +63,7 @@ message Opcode { message MemoryOp { uint32 block_id = 1; MemOp op = 2; - optional native.Expression predicate = 3; + optional native.Expression predicate = 3 [deprecated=true]; } message MemoryInit { uint32 block_id = 1; @@ -98,14 +98,8 @@ message BlackBoxFuncCall { EmbeddedCurveAdd embedded_curve_add = 10; Keccakf1600 keccak_f1600 = 11; RecursiveAggregation recursive_aggregation = 12; - BigIntAdd big_int_add = 13; - BigIntSub big_int_sub = 14; - BigIntMul big_int_mul = 15; - BigIntDiv big_int_div = 16; - BigIntFromLeBytes big_int_from_le_bytes = 17; - BigIntToLeBytes big_int_to_le_bytes = 18; - Poseidon2Permutation poseidon2_permutation = 19; - Sha256Compression sha256_compression = 20; + Poseidon2Permutation poseidon2_permutation = 13; + Sha256Compression sha256_compression = 14; } message AES128Encrypt { repeated FunctionInput inputs = 1; @@ -116,14 +110,16 @@ message BlackBoxFuncCall { message AND { FunctionInput lhs = 1; FunctionInput rhs = 2; - native.Witness output = 3; + uint32 num_bits = 3; + native.Witness output = 4; } message XOR { FunctionInput lhs = 1; FunctionInput rhs = 2; - native.Witness output = 3; + uint32 num_bits = 3; + native.Witness output = 4; } - message RANGE { FunctionInput input = 1; } + message RANGE { FunctionInput input = 1; uint32 num_bits = 2; } message Blake2s { repeated FunctionInput inputs = 1; repeated native.Witness outputs = 2; @@ -137,24 +133,28 @@ message BlackBoxFuncCall { repeated FunctionInput public_key_y = 2; repeated FunctionInput signature = 3; repeated FunctionInput hashed_message = 4; - native.Witness output = 5; + FunctionInput predicate = 5; + native.Witness output = 6; } message EcdsaSecp256r1 { repeated FunctionInput public_key_x = 1; repeated FunctionInput public_key_y = 2; repeated FunctionInput signature = 3; repeated FunctionInput hashed_message = 4; - native.Witness output = 5; + FunctionInput predicate = 5; + native.Witness output = 6; } message MultiScalarMul { repeated FunctionInput points = 1; repeated FunctionInput scalars = 2; - repeated native.Witness outputs = 3; + FunctionInput predicate = 3; + repeated native.Witness outputs = 4; } message EmbeddedCurveAdd { repeated FunctionInput input1 = 1; repeated FunctionInput input2 = 2; - repeated native.Witness outputs = 3; + FunctionInput predicate = 3; + repeated native.Witness outputs = 4; } message Keccakf1600 { repeated FunctionInput inputs = 1; @@ -166,40 +166,11 @@ message BlackBoxFuncCall { repeated FunctionInput public_inputs = 3; FunctionInput key_hash = 4; uint32 proof_type = 5; - } - message BigIntAdd { - uint32 lhs = 1; - uint32 rhs = 2; - uint32 output = 3; - } - message BigIntSub { - uint32 lhs = 1; - uint32 rhs = 2; - uint32 output = 3; - } - message BigIntMul { - uint32 lhs = 1; - uint32 rhs = 2; - uint32 output = 3; - } - message BigIntDiv { - uint32 lhs = 1; - uint32 rhs = 2; - uint32 output = 3; - } - message BigIntFromLeBytes { - repeated FunctionInput inputs = 1; - bytes modulus = 2; - uint32 output = 3; - } - message BigIntToLeBytes { - uint32 input = 1; - repeated native.Witness outputs = 2; + FunctionInput predicate = 6; } message Poseidon2Permutation { repeated FunctionInput inputs = 1; repeated native.Witness outputs = 2; - uint32 len = 3; } message Sha256Compression { repeated FunctionInput inputs = 1; @@ -209,11 +180,6 @@ message BlackBoxFuncCall { } message FunctionInput { - ConstantOrWitnessEnum input = 1; - uint32 num_bits = 2; -} - -message ConstantOrWitnessEnum { oneof value { native.Field constant = 1; native.Witness witness = 2; diff --git a/acvm-repo/acir/src/proto/brillig.proto b/acvm-repo/acir/src/proto/brillig.proto index cba8c797889..dc8c5726c2c 100644 --- a/acvm-repo/acir/src/proto/brillig.proto +++ b/acvm-repo/acir/src/proto/brillig.proto @@ -4,7 +4,7 @@ package acvm.brillig; import "acir/native.proto"; -message BrilligBytecode { repeated BrilligOpcode bytecode = 1; } +message BrilligBytecode { repeated BrilligOpcode bytecode = 1; string function_name = 2; } message BrilligOpcode { oneof value { @@ -12,7 +12,6 @@ message BrilligOpcode { BinaryIntOp binary_int_op = 2; Not not = 3; Cast cast = 4; - JumpIfNot jump_if_not = 5; JumpIf jump_if = 6; Jump jump = 7; CalldataCopy calldata_copy = 8; @@ -52,10 +51,6 @@ message BrilligOpcode { MemoryAddress source = 2; BitSize bit_size = 3; } - message JumpIfNot { - MemoryAddress condition = 1; - uint64 location = 2; - } message JumpIf { MemoryAddress condition = 1; uint64 location = 2; @@ -202,15 +197,9 @@ message BlackBoxOp { EcdsaSecp256r1 ecdsa_secp256r1 = 6; MultiScalarMul multi_scalar_mul = 7; EmbeddedCurveAdd embedded_curve_add = 8; - BigIntAdd big_int_add = 9; - BigIntSub big_int_sub = 10; - BigIntMul big_int_mul = 11; - BigIntDiv big_int_div = 12; - BigIntFromLeBytes big_int_from_le_bytes = 13; - BigIntToLeBytes big_int_to_le_bytes = 14; - Poseidon2Permutation poseidon2_permutation = 15; - Sha256Compression sha256_compression = 16; - ToRadix to_radix = 17; + Poseidon2Permutation poseidon2_permutation = 9; + Sha256Compression sha256_compression = 10; + ToRadix to_radix = 11; } message AES128Encrypt { HeapVector inputs = 1; @@ -259,39 +248,9 @@ message BlackBoxOp { MemoryAddress input2_infinite = 6; HeapArray result = 7; } - message BigIntAdd { - MemoryAddress lhs = 1; - MemoryAddress rhs = 2; - MemoryAddress output = 3; - } - message BigIntSub { - MemoryAddress lhs = 1; - MemoryAddress rhs = 2; - MemoryAddress output = 3; - } - message BigIntMul { - MemoryAddress lhs = 1; - MemoryAddress rhs = 2; - MemoryAddress output = 3; - } - message BigIntDiv { - MemoryAddress lhs = 1; - MemoryAddress rhs = 2; - MemoryAddress output = 3; - } - message BigIntFromLeBytes { - HeapVector inputs = 1; - HeapVector modulus = 2; - MemoryAddress output = 3; - } - message BigIntToLeBytes { - MemoryAddress input = 1; - HeapVector output = 2; - } message Poseidon2Permutation { HeapVector message = 1; HeapArray output = 2; - MemoryAddress len = 3; } message Sha256Compression { HeapArray input = 1; @@ -305,4 +264,4 @@ message BlackBoxOp { MemoryAddress num_limbs = 4; MemoryAddress output_bits = 5; } -} \ No newline at end of file +} diff --git a/acvm-repo/acir/src/proto/convert/acir.rs b/acvm-repo/acir/src/proto/convert/acir.rs index 4c3304613e4..c3075deeacb 100644 --- a/acvm-repo/acir/src/proto/convert/acir.rs +++ b/acvm-repo/acir/src/proto/convert/acir.rs @@ -6,12 +6,12 @@ use crate::{ }, proto::acir::circuit::{ AssertMessage, AssertionPayload, BlackBoxFuncCall, BlockType, BrilligInputs, - BrilligOutputs, Circuit, ConstantOrWitnessEnum, ExpressionOrMemory, ExpressionWidth, - FunctionInput, MemOp, Opcode, OpcodeLocation, + BrilligOutputs, Circuit, ExpressionOrMemory, ExpressionWidth, FunctionInput, MemOp, Opcode, + OpcodeLocation, }, }; use acir_field::AcirField; -use color_eyre::eyre::{self, Context}; +use color_eyre::eyre::{self}; use noir_protobuf::{ProtoCodec, decode_oneof_map}; use super::ProtoSchema; @@ -19,9 +19,9 @@ use super::ProtoSchema; impl ProtoCodec, Circuit> for ProtoSchema { fn encode(value: &circuit::Circuit) -> Circuit { Circuit { + function_name: value.function_name.clone(), current_witness_index: value.current_witness_index, opcodes: Self::encode_vec(&value.opcodes), - expression_width: Self::encode_some(&value.expression_width), private_parameters: Self::encode_vec(value.private_parameters.iter()), public_parameters: Self::encode_vec(value.public_parameters.0.iter()), return_values: Self::encode_vec(value.return_values.0.iter()), @@ -31,9 +31,9 @@ impl ProtoCodec, Circuit> for ProtoSchema { fn decode(value: &Circuit) -> eyre::Result> { Ok(circuit::Circuit { + function_name: value.function_name.clone(), current_witness_index: value.current_witness_index, opcodes: Self::decode_vec_wrap(&value.opcodes, "opcodes")?, - expression_width: Self::decode_some_wrap(&value.expression_width, "expression_width")?, private_parameters: Self::decode_vec_wrap( &value.private_parameters, "private_parameters", @@ -182,11 +182,10 @@ where circuit::Opcode::BlackBoxFuncCall(black_box_func_call) => { Value::BlackboxFuncCall(Self::encode(black_box_func_call)) } - circuit::Opcode::MemoryOp { block_id, op, predicate } => Value::MemoryOp(MemoryOp { - block_id: block_id.0, - op: Self::encode_some(op), - predicate: predicate.as_ref().map(Self::encode), - }), + circuit::Opcode::MemoryOp { block_id, op } => Value::MemoryOp( + #[allow(deprecated)] + MemoryOp { block_id: block_id.0, op: Self::encode_some(op), predicate: None }, + ), circuit::Opcode::MemoryInit { block_id, init, block_type } => { Value::MemoryInit(MemoryInit { block_id: block_id.0, @@ -224,7 +223,6 @@ where Value::MemoryOp(memory_op) => Ok(circuit::Opcode::MemoryOp { block_id: BlockId(memory_op.block_id), op: Self::decode_some_wrap(&memory_op.op, "op")?, - predicate: Self::decode_opt_wrap(&memory_op.predicate, "predicate")?, }), Value::MemoryInit(memory_init) => Ok(circuit::Opcode::MemoryInit { block_id: BlockId(memory_init.block_id), @@ -283,18 +281,20 @@ where outputs: Self::encode_vec(outputs), }) } - opcodes::BlackBoxFuncCall::AND { lhs, rhs, output } => Value::And(And { + opcodes::BlackBoxFuncCall::AND { lhs, rhs, num_bits, output } => Value::And(And { lhs: Self::encode_some(lhs), rhs: Self::encode_some(rhs), + num_bits: *num_bits, output: Self::encode_some(output), }), - opcodes::BlackBoxFuncCall::XOR { lhs, rhs, output } => Value::Xor(Xor { + opcodes::BlackBoxFuncCall::XOR { lhs, rhs, num_bits, output } => Value::Xor(Xor { lhs: Self::encode_some(lhs), rhs: Self::encode_some(rhs), + num_bits: *num_bits, output: Self::encode_some(output), }), - opcodes::BlackBoxFuncCall::RANGE { input } => { - Value::Range(Range { input: Self::encode_some(input) }) + opcodes::BlackBoxFuncCall::RANGE { input, num_bits } => { + Value::Range(Range { input: Self::encode_some(input), num_bits: *num_bits }) } opcodes::BlackBoxFuncCall::Blake2s { inputs, outputs } => Value::Blake2s(Blake2s { inputs: Self::encode_vec(inputs), @@ -310,12 +310,14 @@ where signature, hashed_message, output, + predicate, } => Value::EcdsaSecp256k1(EcdsaSecp256k1 { public_key_x: Self::encode_vec(public_key_x.as_ref()), public_key_y: Self::encode_vec(public_key_y.as_ref()), signature: Self::encode_vec(signature.as_ref()), hashed_message: Self::encode_vec(hashed_message.as_ref()), output: Self::encode_some(output), + predicate: Self::encode_some(predicate), }), opcodes::BlackBoxFuncCall::EcdsaSecp256r1 { public_key_x, @@ -323,26 +325,30 @@ where signature, hashed_message, output, + predicate, } => Value::EcdsaSecp256r1(EcdsaSecp256r1 { public_key_x: Self::encode_vec(public_key_x.as_ref()), public_key_y: Self::encode_vec(public_key_y.as_ref()), signature: Self::encode_vec(signature.as_ref()), hashed_message: Self::encode_vec(hashed_message.as_ref()), output: Self::encode_some(output), + predicate: Self::encode_some(predicate), }), - opcodes::BlackBoxFuncCall::MultiScalarMul { points, scalars, outputs } => { + opcodes::BlackBoxFuncCall::MultiScalarMul { points, scalars, predicate, outputs } => { let (w1, w2, w3) = outputs; Value::MultiScalarMul(MultiScalarMul { points: Self::encode_vec(points), scalars: Self::encode_vec(scalars), + predicate: Self::encode_some(predicate), outputs: Self::encode_vec([w1, w2, w3]), }) } - opcodes::BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, outputs } => { + opcodes::BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, predicate, outputs } => { let (w1, w2, w3) = outputs; Value::EmbeddedCurveAdd(EmbeddedCurveAdd { input1: Self::encode_vec(input1.as_ref()), input2: Self::encode_vec(input2.as_ref()), + predicate: Self::encode_some(predicate), outputs: Self::encode_vec([w1, w2, w3]), }) } @@ -358,43 +364,19 @@ where public_inputs, key_hash, proof_type, + predicate, } => Value::RecursiveAggregation(RecursiveAggregation { verification_key: Self::encode_vec(verification_key), proof: Self::encode_vec(proof), public_inputs: Self::encode_vec(public_inputs), key_hash: Self::encode_some(key_hash), proof_type: *proof_type, + predicate: Self::encode_some(predicate), }), - opcodes::BlackBoxFuncCall::BigIntAdd { lhs, rhs, output } => { - Value::BigIntAdd(BigIntAdd { lhs: *lhs, rhs: *rhs, output: *output }) - } - opcodes::BlackBoxFuncCall::BigIntSub { lhs, rhs, output } => { - Value::BigIntSub(BigIntSub { lhs: *lhs, rhs: *rhs, output: *output }) - } - opcodes::BlackBoxFuncCall::BigIntMul { lhs, rhs, output } => { - Value::BigIntMul(BigIntMul { lhs: *lhs, rhs: *rhs, output: *output }) - } - opcodes::BlackBoxFuncCall::BigIntDiv { lhs, rhs, output } => { - Value::BigIntDiv(BigIntDiv { lhs: *lhs, rhs: *rhs, output: *output }) - } - opcodes::BlackBoxFuncCall::BigIntFromLeBytes { inputs, modulus, output } => { - Value::BigIntFromLeBytes(BigIntFromLeBytes { - inputs: Self::encode_vec(inputs), - modulus: modulus.clone(), - output: *output, - }) - } - opcodes::BlackBoxFuncCall::BigIntToLeBytes { input, outputs } => { - Value::BigIntToLeBytes(BigIntToLeBytes { - input: *input, - outputs: Self::encode_vec(outputs), - }) - } - opcodes::BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs, len } => { + opcodes::BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs } => { Value::Poseidon2Permutation(Poseidon2Permutation { inputs: Self::encode_vec(inputs), outputs: Self::encode_vec(outputs), - len: *len, }) } opcodes::BlackBoxFuncCall::Sha256Compression { inputs, hash_values, outputs } => { @@ -423,15 +405,18 @@ where Value::And(v) => Ok(opcodes::BlackBoxFuncCall::AND { lhs: Self::decode_some_wrap(&v.lhs, "lhs")?, rhs: Self::decode_some_wrap(&v.rhs, "rhs")?, + num_bits: v.num_bits, output: Self::decode_some_wrap(&v.output, "output")?, }), Value::Xor(v) => Ok(opcodes::BlackBoxFuncCall::XOR { lhs: Self::decode_some_wrap(&v.lhs, "lhs")?, rhs: Self::decode_some_wrap(&v.rhs, "rhs")?, + num_bits: v.num_bits, output: Self::decode_some_wrap(&v.output, "output")?, }), Value::Range(v) => Ok(opcodes::BlackBoxFuncCall::RANGE { input: Self::decode_some_wrap(&v.input, "input")?, + num_bits: v.num_bits, }), Value::Blake2s(v) => Ok(opcodes::BlackBoxFuncCall::Blake2s { inputs: Self::decode_vec_wrap(&v.inputs, "inputs")?, @@ -450,6 +435,7 @@ where "hashed_message", )?, output: Self::decode_some_wrap(&v.output, "output")?, + predicate: Self::decode_some_wrap(&v.predicate, "predicate")?, }), Value::EcdsaSecp256r1(v) => Ok(opcodes::BlackBoxFuncCall::EcdsaSecp256r1 { public_key_x: Self::decode_box_arr_wrap(&v.public_key_x, "public_key_x")?, @@ -460,16 +446,19 @@ where "hashed_message", )?, output: Self::decode_some_wrap(&v.output, "output")?, + predicate: Self::decode_some_wrap(&v.predicate, "predicate")?, }), Value::MultiScalarMul(v) => Ok(opcodes::BlackBoxFuncCall::MultiScalarMul { points: Self::decode_vec_wrap(&v.points, "points")?, scalars: Self::decode_vec_wrap(&v.scalars, "scalars")?, + predicate: Self::decode_some_wrap(&v.predicate, "predicate")?, outputs: Self::decode_arr_wrap(&v.outputs, "outputs") .map(|[w1, w2, w3]| (w1, w2, w3))?, }), Value::EmbeddedCurveAdd(v) => Ok(opcodes::BlackBoxFuncCall::EmbeddedCurveAdd { input1: Self::decode_box_arr_wrap(&v.input1, "input1")?, input2: Self::decode_box_arr_wrap(&v.input2, "input2")?, + predicate: Self::decode_some_wrap(&v.predicate, "predicate")?, outputs: Self::decode_arr_wrap(&v.outputs, "outputs") .map(|[w1, w2, w3]| (w1, w2, w3))?, }), @@ -490,44 +479,13 @@ where )?, key_hash: Self::decode_some_wrap(&v.key_hash, "key_hash")?, proof_type: v.proof_type, + predicate: Self::decode_some_wrap(&v.predicate, "predicate")?, }) } - Value::BigIntAdd(v) => Ok(opcodes::BlackBoxFuncCall::BigIntAdd { - lhs: v.lhs, - rhs: v.rhs, - output: v.output, - }), - Value::BigIntSub(v) => Ok(opcodes::BlackBoxFuncCall::BigIntSub { - lhs: v.lhs, - rhs: v.rhs, - output: v.output, - }), - Value::BigIntMul(v) => Ok(opcodes::BlackBoxFuncCall::BigIntMul { - lhs: v.lhs, - rhs: v.rhs, - output: v.output, - }), - Value::BigIntDiv(v) => Ok(opcodes::BlackBoxFuncCall::BigIntDiv { - lhs: v.lhs, - rhs: v.rhs, - output: v.output, - }), - Value::BigIntFromLeBytes(v) => { - Ok(opcodes::BlackBoxFuncCall::BigIntFromLeBytes { - inputs: Self::decode_vec_wrap(&v.inputs, "inputs")?, - modulus: v.modulus.clone(), - output: v.output, - }) - } - Value::BigIntToLeBytes(v) => Ok(opcodes::BlackBoxFuncCall::BigIntToLeBytes { - input: v.input, - outputs: Self::decode_vec_wrap(&v.outputs, "outputs")?, - }), Value::Poseidon2Permutation(v) => { Ok(opcodes::BlackBoxFuncCall::Poseidon2Permutation { inputs: Self::decode_vec_wrap(&v.inputs, "inputs")?, outputs: Self::decode_vec_wrap(&v.outputs, "outputs")?, - len: v.len, }) } Value::Sha256Compression(v) => { @@ -548,46 +506,22 @@ where F: AcirField, { fn encode(value: &opcodes::FunctionInput) -> FunctionInput { - FunctionInput { input: Self::encode_some(value.input_ref()), num_bits: value.num_bits() } - } - - fn decode(value: &FunctionInput) -> eyre::Result> { - let input = Self::decode_some_wrap(&value.input, "input")?; - - match input { - opcodes::ConstantOrWitnessEnum::Constant(c) => { - opcodes::FunctionInput::constant(c, value.num_bits).wrap_err("constant") - } - opcodes::ConstantOrWitnessEnum::Witness(w) => { - Ok(opcodes::FunctionInput::witness(w, value.num_bits)) - } - } - } -} - -impl ProtoCodec, ConstantOrWitnessEnum> for ProtoSchema -where - F: AcirField, -{ - fn encode(value: &opcodes::ConstantOrWitnessEnum) -> ConstantOrWitnessEnum { - use crate::proto::acir::circuit::constant_or_witness_enum::*; + use crate::proto::acir::circuit::function_input::*; let value = match value { - opcodes::ConstantOrWitnessEnum::Constant(field) => Value::Constant(Self::encode(field)), - opcodes::ConstantOrWitnessEnum::Witness(witness) => { - Value::Witness(Self::encode(witness)) - } + opcodes::FunctionInput::Constant(field) => Value::Constant(Self::encode(field)), + opcodes::FunctionInput::Witness(witness) => Value::Witness(Self::encode(witness)), }; - ConstantOrWitnessEnum { value: Some(value) } + FunctionInput { value: Some(value) } } - fn decode(value: &ConstantOrWitnessEnum) -> eyre::Result> { - use crate::proto::acir::circuit::constant_or_witness_enum::*; + fn decode(value: &FunctionInput) -> eyre::Result> { + use crate::proto::acir::circuit::function_input::*; decode_oneof_map(&value.value, |value| match value { Value::Constant(field) => { - Ok(opcodes::ConstantOrWitnessEnum::Constant(Self::decode_wrap(field, "constant")?)) + Ok(opcodes::FunctionInput::Constant(Self::decode_wrap(field, "constant")?)) } Value::Witness(witness) => { - Ok(opcodes::ConstantOrWitnessEnum::Witness(Self::decode_wrap(witness, "witness")?)) + Ok(opcodes::FunctionInput::Witness(Self::decode_wrap(witness, "witness")?)) } }) } diff --git a/acvm-repo/acir/src/proto/convert/brillig.rs b/acvm-repo/acir/src/proto/convert/brillig.rs index 54df85ec4ed..814d3684d9d 100644 --- a/acvm-repo/acir/src/proto/convert/brillig.rs +++ b/acvm-repo/acir/src/proto/convert/brillig.rs @@ -17,11 +17,15 @@ impl ProtoCodec, BrilligBytec for ProtoSchema { fn encode(value: &circuit::brillig::BrilligBytecode) -> BrilligBytecode { - BrilligBytecode { bytecode: Self::encode_vec(&value.bytecode) } + BrilligBytecode { + function_name: value.function_name.clone(), + bytecode: Self::encode_vec(&value.bytecode), + } } fn decode(value: &BrilligBytecode) -> eyre::Result> { Ok(circuit::brillig::BrilligBytecode { + function_name: value.function_name.clone(), bytecode: Self::decode_vec_wrap(&value.bytecode, "bytecode")?, }) } @@ -59,10 +63,6 @@ impl ProtoCodec, BrilligOpcode> for ProtoSchema source: Self::encode_some(source), bit_size: Self::encode_some(bit_size), }), - brillig::Opcode::JumpIfNot { condition, location } => Value::JumpIfNot(JumpIfNot { - condition: Self::encode_some(condition), - location: Self::encode(location), - }), brillig::Opcode::JumpIf { condition, location } => Value::JumpIf(JumpIf { condition: Self::encode_some(condition), location: Self::encode(location), @@ -166,10 +166,6 @@ impl ProtoCodec, BrilligOpcode> for ProtoSchema source: Self::decode_some_wrap(&v.source, "source")?, bit_size: Self::decode_some_wrap(&v.bit_size, "bit_size")?, }), - Value::JumpIfNot(v) => Ok(brillig::Opcode::JumpIfNot { - condition: Self::decode_some_wrap(&v.condition, "condition")?, - location: Self::decode_wrap(&v.location, "location")?, - }), Value::JumpIf(v) => Ok(brillig::Opcode::JumpIf { condition: Self::decode_some_wrap(&v.condition, "condition")?, location: Self::decode_wrap(&v.location, "location")?, @@ -553,44 +549,10 @@ impl ProtoCodec for ProtoSchema { input2_infinite: Self::encode_some(input2_infinite), result: Self::encode_some(result), }), - brillig::BlackBoxOp::BigIntAdd { lhs, rhs, output } => Value::BigIntAdd(BigIntAdd { - lhs: Self::encode_some(lhs), - rhs: Self::encode_some(rhs), - output: Self::encode_some(output), - }), - brillig::BlackBoxOp::BigIntSub { lhs, rhs, output } => Value::BigIntSub(BigIntSub { - lhs: Self::encode_some(lhs), - rhs: Self::encode_some(rhs), - output: Self::encode_some(output), - }), - brillig::BlackBoxOp::BigIntMul { lhs, rhs, output } => Value::BigIntMul(BigIntMul { - lhs: Self::encode_some(lhs), - rhs: Self::encode_some(rhs), - output: Self::encode_some(output), - }), - brillig::BlackBoxOp::BigIntDiv { lhs, rhs, output } => Value::BigIntDiv(BigIntDiv { - lhs: Self::encode_some(lhs), - rhs: Self::encode_some(rhs), - output: Self::encode_some(output), - }), - brillig::BlackBoxOp::BigIntFromLeBytes { inputs, modulus, output } => { - Value::BigIntFromLeBytes(BigIntFromLeBytes { - inputs: Self::encode_some(inputs), - modulus: Self::encode_some(modulus), - output: Self::encode_some(output), - }) - } - brillig::BlackBoxOp::BigIntToLeBytes { input, output } => { - Value::BigIntToLeBytes(BigIntToLeBytes { - input: Self::encode_some(input), - output: Self::encode_some(output), - }) - } - brillig::BlackBoxOp::Poseidon2Permutation { message, output, len } => { + brillig::BlackBoxOp::Poseidon2Permutation { message, output } => { Value::Poseidon2Permutation(Poseidon2Permutation { message: Self::encode_some(message), output: Self::encode_some(output), - len: Self::encode_some(len), }) } brillig::BlackBoxOp::Sha256Compression { input, hash_values, output } => { @@ -666,39 +628,9 @@ impl ProtoCodec for ProtoSchema { input2_infinite: Self::decode_some_wrap(&v.input2_infinite, "input2_infinite")?, result: Self::decode_some_wrap(&v.result, "result")?, }), - Value::BigIntAdd(v) => Ok(brillig::BlackBoxOp::BigIntAdd { - lhs: Self::decode_some_wrap(&v.lhs, "lhs")?, - rhs: Self::decode_some_wrap(&v.rhs, "rhs")?, - output: Self::decode_some_wrap(&v.output, "output")?, - }), - Value::BigIntSub(v) => Ok(brillig::BlackBoxOp::BigIntSub { - lhs: Self::decode_some_wrap(&v.lhs, "lhs")?, - rhs: Self::decode_some_wrap(&v.rhs, "rhs")?, - output: Self::decode_some_wrap(&v.output, "output")?, - }), - Value::BigIntMul(v) => Ok(brillig::BlackBoxOp::BigIntMul { - lhs: Self::decode_some_wrap(&v.lhs, "lhs")?, - rhs: Self::decode_some_wrap(&v.rhs, "rhs")?, - output: Self::decode_some_wrap(&v.output, "output")?, - }), - Value::BigIntDiv(v) => Ok(brillig::BlackBoxOp::BigIntDiv { - lhs: Self::decode_some_wrap(&v.lhs, "lhs")?, - rhs: Self::decode_some_wrap(&v.rhs, "rhs")?, - output: Self::decode_some_wrap(&v.output, "output")?, - }), - Value::BigIntFromLeBytes(v) => Ok(brillig::BlackBoxOp::BigIntFromLeBytes { - inputs: Self::decode_some_wrap(&v.inputs, "inputs")?, - modulus: Self::decode_some_wrap(&v.modulus, "modulus")?, - output: Self::decode_some_wrap(&v.output, "output")?, - }), - Value::BigIntToLeBytes(v) => Ok(brillig::BlackBoxOp::BigIntToLeBytes { - input: Self::decode_some_wrap(&v.input, "input")?, - output: Self::decode_some_wrap(&v.output, "output")?, - }), Value::Poseidon2Permutation(v) => Ok(brillig::BlackBoxOp::Poseidon2Permutation { message: Self::decode_some_wrap(&v.message, "message")?, output: Self::decode_some_wrap(&v.output, "output")?, - len: Self::decode_some_wrap(&v.len, "len")?, }), Value::Sha256Compression(v) => Ok(brillig::BlackBoxOp::Sha256Compression { input: Self::decode_some_wrap(&v.input, "input")?, diff --git a/acvm-repo/acir/src/serialization.rs b/acvm-repo/acir/src/serialization.rs index 9abbec90b0f..6c7b87788b3 100644 --- a/acvm-repo/acir/src/serialization.rs +++ b/acvm-repo/acir/src/serialization.rs @@ -48,12 +48,14 @@ impl Format { /// /// This format is compact, but provides no backwards compatibility. pub(crate) fn bincode_serialize(value: &T) -> std::io::Result> { - bincode::serde::encode_to_vec(value, bincode::config::legacy()).map_err(std::io::Error::other) + let config = bincode::config::legacy().with_limit::<{ u32::MAX as usize }>(); + bincode::serde::encode_to_vec(value, config).map_err(std::io::Error::other) } /// Deserialize a value using `bincode`, based on `serde`. pub(crate) fn bincode_deserialize Deserialize<'a>>(buf: &[u8]) -> std::io::Result { - bincode::serde::borrow_decode_from_slice(buf, bincode::config::legacy()) + let config = bincode::config::legacy().with_limit::<{ u32::MAX as usize }>(); + bincode::serde::borrow_decode_from_slice(buf, config) .map(|(result, _)| result) .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e)) } diff --git a/acvm-repo/acir/tests/test_program_serialization.rs b/acvm-repo/acir/tests/test_program_serialization.rs index 2863bc011d8..a90346673f7 100644 --- a/acvm-repo/acir/tests/test_program_serialization.rs +++ b/acvm-repo/acir/tests/test_program_serialization.rs @@ -47,7 +47,7 @@ fn addition_circuit() { let bytes = Program::serialize_program(&program); - insta::assert_compact_debug_snapshot!(bytes, @"[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, 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]"); + insta::assert_compact_debug_snapshot!(bytes, @"[31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 149, 143, 49, 10, 128, 48, 12, 69, 127, 170, 7, 113, 212, 77, 241, 8, 34, 56, 137, 163, 139, 155, 7, 16, 55, 199, 30, 65, 188, 128, 167, 16, 61, 78, 55, 71, 23, 119, 29, 90, 140, 116, 105, 31, 132, 36, 240, 73, 254, 39, 252, 9, 223, 34, 216, 4, 186, 71, 112, 130, 200, 67, 43, 152, 54, 237, 235, 81, 101, 107, 178, 55, 229, 38, 101, 219, 197, 249, 89, 77, 199, 48, 23, 234, 94, 46, 237, 195, 241, 46, 132, 121, 192, 102, 179, 3, 95, 38, 206, 3, 2, 103, 244, 195, 16, 1, 0, 0]"); let program_de = Program::deserialize_program(&bytes).unwrap(); assert_eq!(program_de, program); @@ -58,19 +58,17 @@ fn multi_scalar_mul_circuit() { let multi_scalar_mul: Opcode = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::MultiScalarMul { points: vec![ - FunctionInput::witness(Witness(1), FieldElement::max_num_bits()), - FunctionInput::witness(Witness(2), FieldElement::max_num_bits()), - FunctionInput::witness(Witness(3), 1), + FunctionInput::Witness(Witness(1)), + FunctionInput::Witness(Witness(2)), + FunctionInput::Witness(Witness(3)), ], - scalars: vec![ - FunctionInput::witness(Witness(4), FieldElement::max_num_bits()), - FunctionInput::witness(Witness(5), FieldElement::max_num_bits()), - ], - outputs: (Witness(6), Witness(7), Witness(8)), + scalars: vec![FunctionInput::Witness(Witness(4)), FunctionInput::Witness(Witness(5))], + predicate: FunctionInput::Witness(Witness(6)), + outputs: (Witness(7), Witness(8), Witness(9)), }); let circuit = Circuit { - current_witness_index: 9, + current_witness_index: 10, opcodes: vec![multi_scalar_mul], private_parameters: BTreeSet::from([ Witness(1), @@ -78,15 +76,16 @@ fn multi_scalar_mul_circuit() { Witness(3), Witness(4), Witness(5), + Witness(6), ]), - return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(6), Witness(7), Witness(8)])), + return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(7), Witness(8), Witness(9)])), ..Circuit::default() }; let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; let bytes = Program::serialize_program(&program); - insta::assert_compact_debug_snapshot!(bytes, @"[31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 77, 9, 10, 0, 48, 8, 114, 107, 231, 255, 255, 59, 86, 204, 64, 22, 136, 102, 89, 5, 175, 182, 163, 80, 7, 47, 135, 73, 31, 56, 228, 42, 218, 196, 203, 221, 38, 243, 78, 61, 28, 147, 119, 65, 31, 146, 53, 230, 210, 135, 252, 255, 179, 90, 23, 212, 196, 199, 187, 192, 0, 0, 0]"); + insta::assert_compact_debug_snapshot!(bytes, @"[31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 141, 11, 10, 0, 32, 12, 66, 87, 235, 127, 255, 3, 183, 224, 5, 214, 64, 84, 68, 151, 236, 189, 21, 72, 232, 195, 35, 224, 226, 47, 50, 236, 232, 155, 23, 184, 194, 45, 208, 217, 153, 120, 147, 13, 167, 83, 37, 51, 249, 169, 221, 255, 54, 129, 45, 40, 232, 188, 0, 0, 0]"); let program_de = Program::deserialize_program(&bytes).unwrap(); assert_eq!(program_de, program); @@ -102,6 +101,7 @@ fn simple_brillig_foreign_call() { let one_usize = MemoryAddress::direct(2); let brillig_bytecode = BrilligBytecode { + function_name: "invert_call".into(), bytecode: vec![ brillig::Opcode::Const { destination: zero_usize, @@ -154,7 +154,7 @@ fn simple_brillig_foreign_call() { let bytes = Program::serialize_program(&program); - insta::assert_compact_debug_snapshot!(bytes, @"[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]"); + insta::assert_compact_debug_snapshot!(bytes, @"[31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 149, 81, 237, 10, 128, 32, 12, 116, 246, 193, 160, 127, 61, 65, 111, 22, 17, 253, 8, 164, 31, 17, 61, 127, 69, 91, 204, 156, 48, 7, 58, 61, 239, 240, 142, 129, 139, 11, 239, 5, 116, 174, 169, 131, 75, 139, 177, 193, 153, 10, 192, 206, 141, 254, 243, 223, 70, 15, 222, 32, 236, 168, 175, 219, 185, 236, 199, 56, 79, 33, 52, 4, 225, 143, 250, 244, 170, 192, 27, 74, 95, 229, 122, 104, 21, 80, 70, 146, 17, 152, 251, 198, 208, 166, 32, 21, 185, 123, 14, 239, 21, 156, 157, 92, 163, 94, 232, 115, 22, 2, 0, 0]"); let program_de = Program::deserialize_program(&bytes).unwrap(); assert_eq!(program_de, program); @@ -175,6 +175,7 @@ fn complex_brillig_foreign_call() { let a_plus_b_plus_c_times_2 = Witness(8); let brillig_bytecode = BrilligBytecode { + function_name: "complex_call".into(), bytecode: vec![ brillig::Opcode::Const { destination: MemoryAddress::direct(0), @@ -294,7 +295,7 @@ fn complex_brillig_foreign_call() { let bytes = Program::serialize_program(&program); - insta::assert_compact_debug_snapshot!(bytes, @"[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]"); + insta::assert_compact_debug_snapshot!(bytes, @"[31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 181, 84, 219, 10, 194, 48, 12, 109, 154, 109, 22, 244, 201, 47, 24, 232, 127, 137, 12, 223, 42, 250, 232, 231, 187, 66, 50, 178, 88, 181, 233, 182, 64, 73, 27, 206, 201, 101, 39, 12, 220, 220, 194, 120, 128, 238, 13, 121, 79, 62, 197, 81, 225, 25, 219, 187, 34, 3, 40, 199, 86, 215, 240, 110, 251, 26, 232, 236, 53, 146, 161, 177, 142, 225, 123, 89, 230, 54, 245, 207, 61, 75, 253, 211, 110, 180, 227, 233, 232, 189, 35, 31, 52, 193, 187, 207, 165, 153, 117, 66, 254, 64, 126, 120, 220, 159, 241, 246, 186, 12, 215, 24, 247, 50, 169, 226, 24, 6, 192, 160, 106, 25, 249, 211, 144, 223, 240, 156, 119, 97, 159, 61, 243, 177, 142, 15, 204, 111, 234, 248, 216, 9, 222, 20, 20, 119, 206, 155, 116, 97, 193, 73, 47, 204, 80, 53, 61, 217, 73, 189, 207, 10, 7, 5, 57, 216, 228, 127, 233, 23, 30, 50, 248, 127, 156, 181, 164, 172, 92, 185, 246, 152, 9, 114, 174, 55, 111, 172, 240, 81, 180, 5, 0, 0]"); let program_de = Program::deserialize_program(&bytes).unwrap(); assert_eq!(program_de, program); @@ -312,12 +313,10 @@ fn memory_op_circuit() { let write = Opcode::MemoryOp { block_id: BlockId(0), op: MemOp::write_to_mem_index(FieldElement::from(1u128).into(), Witness(3).into()), - predicate: None, }; let read = Opcode::MemoryOp { block_id: BlockId(0), op: MemOp::read_at_mem_index(FieldElement::one().into(), Witness(4)), - predicate: None, }; let circuit = Circuit { @@ -331,7 +330,7 @@ fn memory_op_circuit() { let bytes = Program::serialize_program(&program); - insta::assert_compact_debug_snapshot!(bytes, @"[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]"); + insta::assert_compact_debug_snapshot!(bytes, @"[31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 165, 81, 65, 10, 0, 32, 8, 115, 106, 255, 232, 255, 175, 172, 131, 70, 129, 7, 211, 129, 108, 135, 13, 28, 3, 189, 24, 251, 196, 180, 51, 27, 227, 210, 76, 49, 38, 165, 128, 110, 14, 159, 57, 201, 123, 187, 221, 170, 185, 114, 55, 205, 123, 207, 166, 190, 165, 4, 15, 104, 144, 91, 71, 10, 197, 194, 40, 2, 0, 0]"); let program_de = Program::deserialize_program(&bytes).unwrap(); assert_eq!(program_de, program); @@ -429,7 +428,7 @@ fn nested_acir_call_circuit() { let bytes = Program::serialize_program(&program); - insta::assert_compact_debug_snapshot!(bytes, @"[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]"); + insta::assert_compact_debug_snapshot!(bytes, @"[31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 181, 81, 59, 10, 131, 64, 16, 157, 15, 222, 35, 101, 210, 37, 228, 8, 33, 144, 42, 88, 218, 216, 121, 0, 177, 179, 244, 8, 226, 5, 60, 133, 232, 113, 236, 44, 109, 236, 85, 88, 101, 92, 23, 119, 45, 124, 240, 96, 216, 125, 204, 188, 55, 195, 176, 5, 43, 206, 240, 38, 226, 68, 18, 255, 168, 8, 203, 187, 77, 196, 218, 128, 85, 120, 3, 39, 32, 9, 237, 51, 250, 39, 237, 171, 124, 212, 254, 183, 202, 178, 32, 188, 191, 187, 95, 218, 196, 249, 167, 29, 138, 94, 13, 115, 236, 187, 26, 148, 53, 30, 232, 25, 182, 33, 23, 156, 205, 35, 181, 182, 60, 228, 222, 151, 60, 165, 39, 225, 107, 119, 8, 253, 74, 122, 205, 96, 118, 108, 90, 204, 149, 193, 209, 189, 175, 53, 147, 9, 35, 191, 119, 205, 214, 247, 2, 0, 0]"); let program_de = Program::deserialize_program(&bytes).unwrap(); assert_eq!(program_de, program); diff --git a/acvm-repo/acir_field/src/field_element.rs b/acvm-repo/acir_field/src/field_element.rs index 8efeb63927e..bbc843ad1d0 100644 --- a/acvm-repo/acir_field/src/field_element.rs +++ b/acvm-repo/acir_field/src/field_element.rs @@ -69,7 +69,7 @@ impl Serialize for FieldElement { where S: serde::Serializer, { - self.to_hex().serialize(serializer) + self.to_be_bytes().serialize(serializer) } } @@ -78,11 +78,8 @@ impl<'de, T: PrimeField> Deserialize<'de> for FieldElement { where D: serde::Deserializer<'de>, { - let s: Cow<'de, str> = Deserialize::deserialize(deserializer)?; - match Self::from_hex(&s) { - Some(value) => Ok(value), - None => Err(serde::de::Error::custom(format!("Invalid hex for FieldElement: {s}",))), - } + let s: Cow<'de, [u8]> = Deserialize::deserialize(deserializer)?; + Ok(Self::from_be_bytes_reduce(&s)) } } diff --git a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs index b4926bcffbd..d574f8dd6d8 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs @@ -199,13 +199,10 @@ impl MergeExpressionsOptimizer { witnesses } - Opcode::MemoryOp { block_id: _, op, predicate } => { - //index, value, and predicate + Opcode::MemoryOp { block_id: _, op } => { + //index and value let mut witnesses = CircuitSimulator::expr_wit(&op.index); witnesses.extend(CircuitSimulator::expr_wit(&op.value)); - if let Some(p) = predicate { - witnesses.extend(CircuitSimulator::expr_wit(p)); - } witnesses } @@ -341,7 +338,7 @@ mod tests { EXPR [ (1, w0, w1) (1, w5) 0 ] EXPR [ (-1, w2) (1, w4) (1, w5) 0 ] EXPR [ (1, w2) (-1, w3) (1, w4) (1, w5) 0 ] - BLACKBOX::RANGE [(w3, 32)] [] + BLACKBOX::RANGE [w3]:32 bits [] "; let circuit = Circuit::from_str(src).unwrap(); @@ -353,7 +350,7 @@ mod tests { return values: [] EXPR [ (1, w0, w1) (1, w5) 0 ] EXPR [ (2, w0, w0) (-1, w3) (2, w5) 0 ] - BLACKBOX::RANGE [(w3, 32)] [] + BLACKBOX::RANGE [w3]:32 bits [] "); } @@ -369,7 +366,7 @@ mod tests { public parameters: [] return values: [w2] BRILLIG CALL func 0: inputs: [], outputs: [w3] - BLACKBOX::AND [(w0, 8), (w1, 8)] [w4] + BLACKBOX::AND [w0, w1]:8 bits [w4] EXPR [ (1, w3) (-1, w4) 0 ] EXPR [ (-1, w2) (1, w4) 0 ] "; diff --git a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs index 533befb0148..38e743400a1 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs @@ -63,7 +63,7 @@ use acir::{ circuit::{ Circuit, Opcode, brillig::BrilligFunctionId, - opcodes::{BlackBoxFuncCall, BlockId, ConstantOrWitnessEnum, MemOp}, + opcodes::{BlackBoxFuncCall, BlockId, FunctionInput, MemOp}, }, native_types::Witness, }; @@ -125,9 +125,9 @@ impl<'a, F: AcirField> RangeOptimizer<'a, F> { } } - Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { input }) => { - if let ConstantOrWitnessEnum::Witness(witness) = input.input() { - Some((witness, input.num_bits(), false)) + Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { input, num_bits }) => { + if let FunctionInput::Witness(witness) = input { + Some((*witness, *num_bits, false)) } else { None } @@ -192,12 +192,10 @@ impl<'a, F: AcirField> RangeOptimizer<'a, F> { // Going in reverse so we can propagate the side effect information backwards. for (idx, opcode) in self.circuit.opcodes.into_iter().enumerate().rev() { let Some(witness) = (match opcode { - Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { input }) => { - match input.input() { - ConstantOrWitnessEnum::Witness(witness) => Some(witness), - _ => None, - } - } + Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { + input: FunctionInput::Witness(witness), + .. + }) => Some(witness), Opcode::BrilligCall { id, .. } => { // Assume that Brillig calls might have side effects, unless we know they don't. if self.brillig_side_effects.get(&id).copied().unwrap_or(true) { @@ -283,8 +281,8 @@ mod tests { private parameters: [] public parameters: [] return values: [] - BLACKBOX::RANGE [(w1, 32)] [] - BLACKBOX::RANGE [(w1, 16)] [] + BLACKBOX::RANGE [w1]:32 bits [] + BLACKBOX::RANGE [w1]:16 bits [] "; let circuit = Circuit::from_str(src).unwrap(); @@ -307,7 +305,7 @@ mod tests { private parameters: [] public parameters: [] return values: [] - BLACKBOX::RANGE [(w1, 16)] [] + BLACKBOX::RANGE [w1]:16 bits [] "); } @@ -319,10 +317,10 @@ mod tests { private parameters: [] public parameters: [] return values: [] - BLACKBOX::RANGE [(w1, 16)] [] - BLACKBOX::RANGE [(w1, 16)] [] - BLACKBOX::RANGE [(w2, 23)] [] - BLACKBOX::RANGE [(w2, 23)] [] + BLACKBOX::RANGE [w1]:16 bits [] + BLACKBOX::RANGE [w1]:16 bits [] + BLACKBOX::RANGE [w2]:23 bits [] + BLACKBOX::RANGE [w2]:23 bits [] "; let circuit = Circuit::from_str(src).unwrap(); @@ -335,8 +333,8 @@ mod tests { private parameters: [] public parameters: [] return values: [] - BLACKBOX::RANGE [(w1, 16)] [] - BLACKBOX::RANGE [(w2, 23)] [] + BLACKBOX::RANGE [w1]:16 bits [] + BLACKBOX::RANGE [w2]:23 bits [] "); } @@ -349,8 +347,8 @@ mod tests { private parameters: [] public parameters: [] return values: [] - BLACKBOX::RANGE [(w1, 16)] [] - BLACKBOX::RANGE [(w1, 16)] [] + BLACKBOX::RANGE [w1]:16 bits [] + BLACKBOX::RANGE [w1]:16 bits [] EXPR [ 0 ] EXPR [ 0 ] EXPR [ 0 ] @@ -367,7 +365,7 @@ mod tests { private parameters: [] public parameters: [] return values: [] - BLACKBOX::RANGE [(w1, 16)] [] + BLACKBOX::RANGE [w1]:16 bits [] EXPR [ 0 ] EXPR [ 0 ] EXPR [ 0 ] @@ -383,7 +381,7 @@ mod tests { private parameters: [] public parameters: [] return values: [] - BLACKBOX::RANGE [(w1, 16)] [] + BLACKBOX::RANGE [w1]:16 bits [] EXPR [ (1, w1) 0 ] "; let circuit = Circuit::from_str(src).unwrap(); @@ -409,17 +407,17 @@ mod tests { private parameters: [] public parameters: [] return values: [] - BLACKBOX::RANGE [(w1, 32)] [] + BLACKBOX::RANGE [w1]:32 bits [] // Call brillig with w2 BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [] - BLACKBOX::RANGE [(w1, 16)] [] + BLACKBOX::RANGE [w1]:16 bits [] // Another call BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [] // One more constraint, but this is redundant. - BLACKBOX::RANGE [(w1, 64)] [] + BLACKBOX::RANGE [w1]:64 bits [] // assert w1 == 0 EXPR [ (1, w1) 0 ] @@ -436,15 +434,15 @@ mod tests { let (optimized_circuit, _) = optimizer.replace_redundant_ranges(acir_opcode_positions.clone()); - // `BLACKBOX::RANGE [(w1, 32)] []` remains: The minimum does not propagate backwards. + // `BLACKBOX::RANGE [w1]:32 bits []` remains: The minimum does not propagate backwards. assert_circuit_snapshot!(optimized_circuit, @r" current witness: w1 private parameters: [] public parameters: [] return values: [] - BLACKBOX::RANGE [(w1, 32)] [] + BLACKBOX::RANGE [w1]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [] - BLACKBOX::RANGE [(w1, 16)] [] + BLACKBOX::RANGE [w1]:16 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [] EXPR [ (1, w1) 0 ] "); @@ -464,7 +462,7 @@ mod tests { private parameters: [] public parameters: [] return values: [] - BLACKBOX::RANGE [(w1, 16)] [] + BLACKBOX::RANGE [w1]:16 bits [] INIT (id: 0, len: 8, witnesses: [w0, w0, w0, w0, w0, w0, w0, w0]) MEM (id: 0, read at: EXPR [ (1, w1) 0 ], value: EXPR [ (1, w2) 0 ]) "; diff --git a/acvm-repo/acvm/src/compiler/simulator.rs b/acvm-repo/acvm/src/compiler/simulator.rs index 8a32f4b5872..d916dd19eda 100644 --- a/acvm-repo/acvm/src/compiler/simulator.rs +++ b/acvm-repo/acvm/src/compiler/simulator.rs @@ -74,20 +74,14 @@ impl CircuitSimulator { } true } - Opcode::MemoryOp { block_id, op, predicate } => { + Opcode::MemoryOp { block_id, op } => { if !self.initialized_blocks.contains(block_id) { // Memory must be initialized before it can be used. return false; } - if !self.can_solve_expression(&op.index) { return false; } - if let Some(predicate) = predicate { - if !self.can_solve_expression(predicate) { - return false; - } - } if op.operation.is_zero() { let Some(w) = op.value.to_witness() else { return false; @@ -154,8 +148,8 @@ impl CircuitSimulator { } pub fn can_solve_function_input(&self, input: &FunctionInput) -> bool { - if !input.is_constant() { - return self.solvable_witness.contains(&input.to_witness()); + if let FunctionInput::Witness(w) = input { + return self.solvable_witness.contains(w); } true } @@ -200,7 +194,7 @@ mod tests { FieldElement, acir_field::AcirField, circuit::{ - Circuit, ExpressionWidth, Opcode, PublicInputs, + Circuit, Opcode, PublicInputs, brillig::{BrilligFunctionId, BrilligInputs}, opcodes::{BlockId, BlockType, MemOp}, }, @@ -213,8 +207,8 @@ mod tests { public_parameters: PublicInputs, ) -> Circuit { Circuit { + function_name: "test_circuit".to_string(), current_witness_index: 1, - expression_width: ExpressionWidth::Bounded { width: 4 }, opcodes, private_parameters, public_parameters, @@ -306,7 +300,6 @@ mod tests { }, Witness(2), ), - predicate: None, }, ], BTreeSet::from([Witness(1)]), diff --git a/acvm-repo/acvm/src/compiler/transformers/mod.rs b/acvm-repo/acvm/src/compiler/transformers/mod.rs index 8eaae7bb232..0029bbf5e1f 100644 --- a/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -3,7 +3,7 @@ use std::collections::BTreeMap; use acir::{ AcirField, circuit::{ - self, Circuit, ExpressionWidth, Opcode, + Circuit, ExpressionWidth, Opcode, brillig::{BrilligFunctionId, BrilligInputs, BrilligOutputs}, opcodes::{BlackBoxFuncCall, FunctionInput, MemOp}, }, @@ -230,7 +230,6 @@ fn transform_internal_once( acir = Circuit { current_witness_index, - expression_width, opcodes: transformed_opcodes, // The transformer does not add new public inputs ..acir @@ -317,14 +316,11 @@ where self.fold_expr(expr); } Opcode::BlackBoxFuncCall(call) => self.fold_blackbox(call), - Opcode::MemoryOp { block_id: _, op, predicate } => { + Opcode::MemoryOp { block_id: _, op } => { let MemOp { operation, index, value } = op; self.fold_expr(operation); self.fold_expr(index); self.fold_expr(value); - if let Some(pred) = predicate { - self.fold_expr(pred); - } } Opcode::MemoryInit { block_id: _, init, block_type: _ } => { for w in init { @@ -390,30 +386,30 @@ where fn fold_blackbox(&mut self, call: &BlackBoxFuncCall) { match call { BlackBoxFuncCall::AES128Encrypt { inputs, iv, key, outputs } => { - self.fold_function_inputs(inputs.as_slice()); - self.fold_function_inputs(iv.as_slice()); - self.fold_function_inputs(key.as_slice()); + self.fold_inputs(inputs.as_slice()); + self.fold_inputs(iv.as_slice()); + self.fold_inputs(key.as_slice()); self.fold_many(outputs.iter()); } - BlackBoxFuncCall::AND { lhs, rhs, output } => { - self.fold_function_input(lhs); - self.fold_function_input(rhs); + BlackBoxFuncCall::AND { lhs, rhs, output, .. } => { + self.fold_input(lhs); + self.fold_input(rhs); self.fold(*output); } - BlackBoxFuncCall::XOR { lhs, rhs, output } => { - self.fold_function_input(lhs); - self.fold_function_input(rhs); + BlackBoxFuncCall::XOR { lhs, rhs, output, .. } => { + self.fold_input(lhs); + self.fold_input(rhs); self.fold(*output); } - BlackBoxFuncCall::RANGE { input } => { - self.fold_function_input(input); + BlackBoxFuncCall::RANGE { input, .. } => { + self.fold_input(input); } BlackBoxFuncCall::Blake2s { inputs, outputs } => { - self.fold_function_inputs(inputs.as_slice()); + self.fold_inputs(inputs.as_slice()); self.fold_many(outputs.iter()); } BlackBoxFuncCall::Blake3 { inputs, outputs } => { - self.fold_function_inputs(inputs.as_slice()); + self.fold_inputs(inputs.as_slice()); self.fold_many(outputs.iter()); } BlackBoxFuncCall::EcdsaSecp256k1 { @@ -422,12 +418,14 @@ where signature, hashed_message, output, + predicate, } => { - self.fold_function_inputs(public_key_x.as_slice()); - self.fold_function_inputs(public_key_y.as_slice()); - self.fold_function_inputs(signature.as_slice()); - self.fold_function_inputs(hashed_message.as_slice()); + self.fold_inputs(public_key_x.as_slice()); + self.fold_inputs(public_key_y.as_slice()); + self.fold_inputs(signature.as_slice()); + self.fold_inputs(hashed_message.as_slice()); self.fold(*output); + self.fold_input(predicate); } BlackBoxFuncCall::EcdsaSecp256r1 { public_key_x, @@ -435,31 +433,35 @@ where signature, hashed_message, output, + predicate, } => { - self.fold_function_inputs(public_key_x.as_slice()); - self.fold_function_inputs(public_key_y.as_slice()); - self.fold_function_inputs(signature.as_slice()); - self.fold_function_inputs(hashed_message.as_slice()); + self.fold_inputs(public_key_x.as_slice()); + self.fold_inputs(public_key_y.as_slice()); + self.fold_inputs(signature.as_slice()); + self.fold_inputs(hashed_message.as_slice()); self.fold(*output); + self.fold_input(predicate); } - BlackBoxFuncCall::MultiScalarMul { points, scalars, outputs } => { - self.fold_function_inputs(points.as_slice()); - self.fold_function_inputs(scalars.as_slice()); + BlackBoxFuncCall::MultiScalarMul { points, scalars, predicate, outputs } => { + self.fold_inputs(points.as_slice()); + self.fold_inputs(scalars.as_slice()); + self.fold_input(predicate); let (x, y, i) = outputs; self.fold(*x); self.fold(*y); self.fold(*i); } - BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, outputs } => { - self.fold_function_inputs(input1.as_slice()); - self.fold_function_inputs(input2.as_slice()); + BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, predicate, outputs } => { + self.fold_inputs(input1.as_slice()); + self.fold_inputs(input2.as_slice()); + self.fold_input(predicate); let (x, y, i) = outputs; self.fold(*x); self.fold(*y); self.fold(*i); } BlackBoxFuncCall::Keccakf1600 { inputs, outputs } => { - self.fold_function_inputs(inputs.as_slice()); + self.fold_inputs(inputs.as_slice()); self.fold_many(outputs.iter()); } BlackBoxFuncCall::RecursiveAggregation { @@ -468,43 +470,35 @@ where public_inputs, key_hash, proof_type: _, + predicate, } => { - self.fold_function_inputs(verification_key.as_slice()); - self.fold_function_inputs(proof.as_slice()); - self.fold_function_inputs(public_inputs.as_slice()); - self.fold_function_input(key_hash); - } - BlackBoxFuncCall::BigIntAdd { .. } - | BlackBoxFuncCall::BigIntSub { .. } - | BlackBoxFuncCall::BigIntMul { .. } - | BlackBoxFuncCall::BigIntDiv { .. } => {} - BlackBoxFuncCall::BigIntFromLeBytes { inputs, modulus: _, output: _ } => { - self.fold_function_inputs(inputs.as_slice()); + self.fold_inputs(verification_key.as_slice()); + self.fold_inputs(proof.as_slice()); + self.fold_inputs(public_inputs.as_slice()); + self.fold_input(key_hash); + self.fold_input(predicate); } - BlackBoxFuncCall::BigIntToLeBytes { input: _, outputs } => { - self.fold_many(outputs.iter()); - } - BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs, len: _ } => { - self.fold_function_inputs(inputs.as_slice()); + BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs } => { + self.fold_inputs(inputs.as_slice()); self.fold_many(outputs.iter()); } BlackBoxFuncCall::Sha256Compression { inputs, hash_values, outputs } => { - self.fold_function_inputs(inputs.as_slice()); - self.fold_function_inputs(hash_values.as_slice()); + self.fold_inputs(inputs.as_slice()); + self.fold_inputs(hash_values.as_slice()); self.fold_many(outputs.iter()); } } } - fn fold_function_input(&mut self, input: &FunctionInput) { - if let circuit::opcodes::ConstantOrWitnessEnum::Witness(witness) = input.input() { - self.fold(witness); + fn fold_inputs(&mut self, inputs: &[FunctionInput]) { + for input in inputs { + self.fold_input(input); } } - fn fold_function_inputs(&mut self, inputs: &[FunctionInput]) { - for input in inputs { - self.fold_function_input(input); + fn fold_input(&mut self, input: &FunctionInput) { + if let FunctionInput::Witness(witness) = input { + self.fold(*witness); } } } diff --git a/acvm-repo/acvm/src/pwg/blackbox/bigint.rs b/acvm-repo/acvm/src/pwg/blackbox/bigint.rs deleted file mode 100644 index 5a2540df9d6..00000000000 --- a/acvm-repo/acvm/src/pwg/blackbox/bigint.rs +++ /dev/null @@ -1,69 +0,0 @@ -use crate::pwg::input_to_value; -use acir::{ - AcirField, BlackBoxFunc, - circuit::opcodes::FunctionInput, - native_types::{Witness, WitnessMap}, -}; -use acvm_blackbox_solver::BigIntSolver; - -use crate::pwg::OpcodeResolutionError; - -/// Resolve BigInt opcodes by storing BigInt values (and their moduli) by their ID in the BigIntSolver -/// - When it encounters a bigint operation opcode, it performs the operation on the stored values -/// and store the result using the provided ID. -/// - When it gets a to_bytes opcode, it simply looks up the value and resolves the output witness accordingly. -pub(crate) struct AcvmBigIntSolver { - bigint_solver: BigIntSolver, -} - -impl AcvmBigIntSolver { - pub(crate) fn with_pedantic_solving(pedantic_solving: bool) -> AcvmBigIntSolver { - let bigint_solver = BigIntSolver::with_pedantic_solving(pedantic_solving); - AcvmBigIntSolver { bigint_solver } - } - - pub(crate) fn bigint_from_bytes( - &mut self, - inputs: &[FunctionInput], - modulus: &[u8], - output: u32, - initial_witness: &mut WitnessMap, - ) -> Result<(), OpcodeResolutionError> { - let bytes = inputs - .iter() - .map(|input| input_to_value(initial_witness, *input, false).unwrap().to_u128() as u8) - .collect::>(); - self.bigint_solver.bigint_from_bytes(&bytes, modulus, output)?; - Ok(()) - } - - pub(crate) fn bigint_to_bytes( - &self, - input: u32, - outputs: &[Witness], - initial_witness: &mut WitnessMap, - ) -> Result<(), OpcodeResolutionError> { - if self.bigint_solver.pedantic_solving() && outputs.len() != 32 { - panic!("--pedantic-solving: bigint_to_bytes: outputs.len() != 32: {}", outputs.len()); - } - let mut bytes = self.bigint_solver.bigint_to_bytes(input)?; - while bytes.len() < outputs.len() { - bytes.push(0); - } - bytes.iter().zip(outputs.iter()).for_each(|(byte, output)| { - initial_witness.insert(*output, F::from(u128::from(*byte))); - }); - Ok(()) - } - - pub(crate) fn bigint_op( - &mut self, - lhs: u32, - rhs: u32, - output: u32, - func: BlackBoxFunc, - ) -> Result<(), OpcodeResolutionError> { - self.bigint_solver.bigint_op(lhs, rhs, output, func)?; - Ok(()) - } -} diff --git a/acvm-repo/acvm/src/pwg/blackbox/embedded_curve_ops.rs b/acvm-repo/acvm/src/pwg/blackbox/embedded_curve_ops.rs index 2c728e77304..fb34a01faae 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/embedded_curve_ops.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/embedded_curve_ops.rs @@ -15,11 +15,11 @@ pub(super) fn multi_scalar_mul( outputs: (Witness, Witness, Witness), ) -> Result<(), OpcodeResolutionError> { let points: Result, _> = - points.iter().map(|input| input_to_value(initial_witness, *input, false)).collect(); + points.iter().map(|input| input_to_value(initial_witness, *input)).collect(); let points: Vec<_> = points?.into_iter().collect(); let scalars: Result, _> = - scalars.iter().map(|input| input_to_value(initial_witness, *input, false)).collect(); + scalars.iter().map(|input| input_to_value(initial_witness, *input)).collect(); let mut scalars_lo = Vec::new(); let mut scalars_hi = Vec::new(); for (i, scalar) in scalars?.into_iter().enumerate() { @@ -47,12 +47,12 @@ pub(super) fn embedded_curve_add( input2: [FunctionInput; 3], outputs: (Witness, Witness, Witness), ) -> Result<(), OpcodeResolutionError> { - let input1_x = input_to_value(initial_witness, input1[0], false)?; - let input1_y = input_to_value(initial_witness, input1[1], false)?; - let input1_infinite = input_to_value(initial_witness, input1[2], false)?; - let input2_x = input_to_value(initial_witness, input2[0], false)?; - let input2_y = input_to_value(initial_witness, input2[1], false)?; - let input2_infinite = input_to_value(initial_witness, input2[2], false)?; + let input1_x = input_to_value(initial_witness, input1[0])?; + let input1_y = input_to_value(initial_witness, input1[1])?; + let input1_infinite = input_to_value(initial_witness, input1[2])?; + let input2_x = input_to_value(initial_witness, input2[0])?; + let input2_y = input_to_value(initial_witness, input2[1])?; + let input2_infinite = input_to_value(initial_witness, input2[2])?; let (res_x, res_y, res_infinite) = backend.ec_add( &input1_x, &input1_y, diff --git a/acvm-repo/acvm/src/pwg/blackbox/hash.rs b/acvm-repo/acvm/src/pwg/blackbox/hash.rs index c7a1fc75df2..369214557df 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/hash.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/hash.rs @@ -12,12 +12,13 @@ use crate::pwg::{input_to_value, insert_value}; /// If successful, `initial_witness` will be mutated to contain the new witness assignment. pub(super) fn solve_generic_256_hash_opcode( initial_witness: &mut WitnessMap, - inputs: &[FunctionInput], + #[allow(clippy::ptr_arg)] //Clippy mistakenly believes that it can be replaced by &[..] + inputs: &Vec>, var_message_size: Option<&FunctionInput>, outputs: &[Witness; 32], hash_function: fn(data: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError>, ) -> Result<(), OpcodeResolutionError> { - let message_input = get_hash_input(initial_witness, inputs, var_message_size)?; + let message_input = get_hash_input(initial_witness, inputs, var_message_size, 8)?; let digest: [u8; 32] = hash_function(&message_input)?; write_digest_to_outputs(initial_witness, outputs, digest) @@ -28,13 +29,12 @@ fn get_hash_input( initial_witness: &WitnessMap, inputs: &[FunctionInput], message_size: Option<&FunctionInput>, + num_bits: usize, ) -> Result, OpcodeResolutionError> { // Read witness assignments. let mut message_input = Vec::new(); for input in inputs.iter() { - let num_bits = input.num_bits() as usize; - - let witness_assignment = input_to_value(initial_witness, *input, false)?; + let witness_assignment = input_to_value(initial_witness, *input)?; let bytes = witness_assignment.fetch_nearest_bytes(num_bits); message_input.extend(bytes); } @@ -42,8 +42,7 @@ fn get_hash_input( // Truncate the message if there is a `message_size` parameter given match message_size { Some(input) => { - let num_bytes_to_take = - input_to_value(initial_witness, *input, false)?.to_u128() as usize; + let num_bytes_to_take = input_to_value(initial_witness, *input)?.to_u128() as usize; // If the number of bytes to take is more than the amount of bytes available // in the message, then we error. @@ -83,7 +82,7 @@ fn to_u32_array( ) -> Result<[u32; N], OpcodeResolutionError> { let mut result = [0; N]; for (it, input) in result.iter_mut().zip(inputs) { - let witness_value = input_to_value(initial_witness, *input, false)?; + let witness_value = input_to_value(initial_witness, *input)?; *it = witness_value.to_u128() as u32; } Ok(result) @@ -112,25 +111,14 @@ pub(crate) fn solve_poseidon2_permutation_opcode( initial_witness: &mut WitnessMap, inputs: &[FunctionInput], outputs: &[Witness], - len: u32, ) -> Result<(), OpcodeResolutionError> { - if len as usize != inputs.len() { + if inputs.len() != outputs.len() { return Err(OpcodeResolutionError::BlackBoxFunctionFailed( acir::BlackBoxFunc::Poseidon2Permutation, format!( - "the number of inputs does not match specified length. {} != {}", + "the input and output sizes are not consistent. {} != {}", inputs.len(), - len - ), - )); - } - if len as usize != outputs.len() { - return Err(OpcodeResolutionError::BlackBoxFunctionFailed( - acir::BlackBoxFunc::Poseidon2Permutation, - format!( - "the number of outputs does not match specified length. {} != {}", - outputs.len(), - len + outputs.len() ), )); } @@ -138,10 +126,10 @@ pub(crate) fn solve_poseidon2_permutation_opcode( // Read witness assignments let state: Vec = inputs .iter() - .map(|input| input_to_value(initial_witness, *input, false)) + .map(|input| input_to_value(initial_witness, *input)) .collect::>()?; - let state = backend.poseidon2_permutation(&state, len)?; + let state = backend.poseidon2_permutation(&state)?; // Write witness assignments for (output_witness, value) in outputs.iter().zip(state.into_iter()) { diff --git a/acvm-repo/acvm/src/pwg/blackbox/logic.rs b/acvm-repo/acvm/src/pwg/blackbox/logic.rs index 587add11b81..80c377cdaf4 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/logic.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/logic.rs @@ -1,8 +1,8 @@ use crate::OpcodeResolutionError; -use crate::pwg::{input_to_value, insert_value}; +use crate::pwg::{check_bit_size, input_to_value, insert_value}; +use acir::circuit::opcodes::FunctionInput; use acir::{ AcirField, - circuit::opcodes::FunctionInput, native_types::{Witness, WitnessMap}, }; use acvm_blackbox_solver::{bit_and, bit_xor}; @@ -13,17 +13,19 @@ pub(super) fn and( initial_witness: &mut WitnessMap, lhs: &FunctionInput, rhs: &FunctionInput, + num_bits: u32, output: &Witness, pedantic_solving: bool, ) -> Result<(), OpcodeResolutionError> { - assert_eq!( - lhs.num_bits(), - rhs.num_bits(), - "number of bits specified for each input must be the same" - ); - solve_logic_opcode(initial_witness, lhs, rhs, *output, pedantic_solving, |left, right| { - bit_and(left, right, lhs.num_bits()) - }) + solve_logic_opcode( + initial_witness, + lhs, + rhs, + num_bits, + *output, + pedantic_solving, + |left, right| bit_and(left, right, num_bits), + ) } /// Solves a [`BlackBoxFunc::XOR`][acir::circuit::black_box_functions::BlackBoxFunc::XOR] opcode and inserts @@ -32,17 +34,19 @@ pub(super) fn xor( initial_witness: &mut WitnessMap, lhs: &FunctionInput, rhs: &FunctionInput, + num_bits: u32, output: &Witness, pedantic_solving: bool, ) -> Result<(), OpcodeResolutionError> { - assert_eq!( - lhs.num_bits(), - rhs.num_bits(), - "number of bits specified for each input must be the same" - ); - solve_logic_opcode(initial_witness, lhs, rhs, *output, pedantic_solving, |left, right| { - bit_xor(left, right, lhs.num_bits()) - }) + solve_logic_opcode( + initial_witness, + lhs, + rhs, + num_bits, + *output, + pedantic_solving, + |left, right| bit_xor(left, right, num_bits), + ) } /// Derives the rest of the witness based on the initial low level variables @@ -50,6 +54,7 @@ fn solve_logic_opcode( initial_witness: &mut WitnessMap, a: &FunctionInput, b: &FunctionInput, + num_bits: u32, result: Witness, pedantic_solving: bool, logic_op: impl Fn(F, F) -> F, @@ -58,9 +63,12 @@ fn solve_logic_opcode( // default once we figure out how to combine these with existing // noirc_frontend/noirc_evaluator overflow error messages let skip_bitsize_checks = !pedantic_solving; - let w_l_value = input_to_value(initial_witness, *a, skip_bitsize_checks)?; - let w_r_value = input_to_value(initial_witness, *b, skip_bitsize_checks)?; + let w_l_value = input_to_value(initial_witness, *a)?; + let w_r_value = input_to_value(initial_witness, *b)?; let assignment = logic_op(w_l_value, w_r_value); - + if !skip_bitsize_checks { + check_bit_size(w_l_value, num_bits)?; + check_bit_size(w_r_value, num_bits)?; + } insert_value(&result, assignment, initial_witness) } diff --git a/acvm-repo/acvm/src/pwg/blackbox/mod.rs b/acvm-repo/acvm/src/pwg/blackbox/mod.rs index 0c1c2d0484b..950ed1dc6a5 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/mod.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/mod.rs @@ -1,20 +1,16 @@ use acir::{ AcirField, - circuit::opcodes::{BlackBoxFuncCall, ConstantOrWitnessEnum, FunctionInput}, + circuit::opcodes::{BlackBoxFuncCall, FunctionInput}, native_types::{Witness, WitnessMap}, }; use acvm_blackbox_solver::{blake2s, blake3, keccakf1600}; -use self::{ - aes128::solve_aes128_encryption_opcode, bigint::AcvmBigIntSolver, - hash::solve_poseidon2_permutation_opcode, -}; +use self::{aes128::solve_aes128_encryption_opcode, hash::solve_poseidon2_permutation_opcode}; use super::{OpcodeNotSolvable, OpcodeResolutionError, insert_value}; use crate::{BlackBoxFunctionSolver, pwg::input_to_value}; mod aes128; -pub(crate) mod bigint; mod embedded_curve_ops; mod hash; mod logic; @@ -37,7 +33,7 @@ fn first_missing_assignment( inputs: &[FunctionInput], ) -> Option { inputs.iter().find_map(|input| { - if let ConstantOrWitnessEnum::Witness(witness) = input.input_ref() { + if let FunctionInput::Witness(witness) = input { if witness_assignments.contains_key(witness) { None } else { Some(*witness) } } else { None @@ -70,7 +66,6 @@ pub(crate) fn solve( backend: &impl BlackBoxFunctionSolver, initial_witness: &mut WitnessMap, bb_func: &BlackBoxFuncCall, - bigint_solver: &mut AcvmBigIntSolver, ) -> Result<(), OpcodeResolutionError> { let inputs = bb_func.get_inputs_vec(); if !contains_all_inputs(initial_witness, &inputs) { @@ -85,27 +80,27 @@ pub(crate) fn solve( BlackBoxFuncCall::AES128Encrypt { inputs, iv, key, outputs } => { solve_aes128_encryption_opcode(initial_witness, inputs, iv, key, outputs) } - BlackBoxFuncCall::AND { lhs, rhs, output } => { - and(initial_witness, lhs, rhs, output, backend.pedantic_solving()) + BlackBoxFuncCall::AND { lhs, rhs, num_bits, output } => { + and(initial_witness, lhs, rhs, *num_bits, output, backend.pedantic_solving()) } - BlackBoxFuncCall::XOR { lhs, rhs, output } => { - xor(initial_witness, lhs, rhs, output, backend.pedantic_solving()) + BlackBoxFuncCall::XOR { lhs, rhs, num_bits, output } => { + xor(initial_witness, lhs, rhs, *num_bits, output, backend.pedantic_solving()) } - BlackBoxFuncCall::RANGE { input } => { - solve_range_opcode(initial_witness, input, backend.pedantic_solving()) + BlackBoxFuncCall::RANGE { input, num_bits } => { + solve_range_opcode(initial_witness, input, *num_bits) } - BlackBoxFuncCall::Blake2s { inputs, outputs } => { - solve_generic_256_hash_opcode(initial_witness, inputs, None, outputs, blake2s) + BlackBoxFuncCall::Blake2s { outputs, .. } => { + let inputs = bb_func.get_inputs_vec(); + solve_generic_256_hash_opcode(initial_witness, &inputs, None, outputs, blake2s) } - BlackBoxFuncCall::Blake3 { inputs, outputs } => { - solve_generic_256_hash_opcode(initial_witness, inputs, None, outputs, blake3) + BlackBoxFuncCall::Blake3 { outputs, .. } => { + let inputs = bb_func.get_inputs_vec(); + solve_generic_256_hash_opcode(initial_witness, &inputs, None, outputs, blake3) } BlackBoxFuncCall::Keccakf1600 { inputs, outputs } => { let mut state = [0; 25]; for (it, input) in state.iter_mut().zip(inputs.as_ref()) { - let num_bits = input.num_bits() as usize; - assert_eq!(num_bits, 64); - let witness_assignment = input_to_value(initial_witness, *input, false)?; + let witness_assignment = input_to_value(initial_witness, *input)?; let lane = witness_assignment.try_to_u64(); *it = lane.unwrap(); } @@ -121,6 +116,7 @@ pub(crate) fn solve( signature, hashed_message: message, output, + .. } => secp256k1_prehashed( initial_witness, public_key_x, @@ -135,6 +131,7 @@ pub(crate) fn solve( signature, hashed_message: message, output, + .. } => secp256r1_prehashed( initial_witness, public_key_x, @@ -143,31 +140,19 @@ pub(crate) fn solve( message.as_ref(), *output, ), - BlackBoxFuncCall::MultiScalarMul { points, scalars, outputs } => { + BlackBoxFuncCall::MultiScalarMul { points, scalars, outputs, .. } => { multi_scalar_mul(backend, initial_witness, points, scalars, *outputs) } - BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, outputs } => { + BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, outputs, .. } => { embedded_curve_add(backend, initial_witness, **input1, **input2, *outputs) } // Recursive aggregation will be entirely handled by the backend and is not solved by the ACVM BlackBoxFuncCall::RecursiveAggregation { .. } => Ok(()), - BlackBoxFuncCall::BigIntAdd { lhs, rhs, output } - | BlackBoxFuncCall::BigIntSub { lhs, rhs, output } - | BlackBoxFuncCall::BigIntMul { lhs, rhs, output } - | BlackBoxFuncCall::BigIntDiv { lhs, rhs, output } => { - bigint_solver.bigint_op(*lhs, *rhs, *output, bb_func.get_black_box_func()) - } - BlackBoxFuncCall::BigIntFromLeBytes { inputs, modulus, output } => { - bigint_solver.bigint_from_bytes(inputs, modulus, *output, initial_witness) - } - BlackBoxFuncCall::BigIntToLeBytes { input, outputs } => { - bigint_solver.bigint_to_bytes(*input, outputs, initial_witness) - } BlackBoxFuncCall::Sha256Compression { inputs, hash_values, outputs } => { solve_sha_256_permutation_opcode(initial_witness, inputs, hash_values, outputs) } - BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs, len } => { - solve_poseidon2_permutation_opcode(backend, initial_witness, inputs, outputs, *len) + BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs } => { + solve_poseidon2_permutation_opcode(backend, initial_witness, inputs, outputs) } } } diff --git a/acvm-repo/acvm/src/pwg/blackbox/range.rs b/acvm-repo/acvm/src/pwg/blackbox/range.rs index 67d44b21f3f..c27be0bdc23 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/range.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/range.rs @@ -7,13 +7,11 @@ use acir::{AcirField, circuit::opcodes::FunctionInput, native_types::WitnessMap} pub(crate) fn solve_range_opcode( initial_witness: &WitnessMap, input: &FunctionInput, - pedantic_solving: bool, + num_bits: u32, ) -> Result<(), OpcodeResolutionError> { - // TODO(https://github.com/noir-lang/noir/issues/5985): - // re-enable bitsize checks by default - let skip_bitsize_checks = !pedantic_solving; - let w_value = input_to_value(initial_witness, *input, skip_bitsize_checks)?; - if w_value.num_bits() > input.num_bits() { + let w_value = input_to_value(initial_witness, *input)?; + + if w_value.num_bits() > num_bits { return Err(OpcodeResolutionError::UnsatisfiedConstrain { opcode_location: ErrorLocation::Unresolved, payload: None, @@ -38,15 +36,15 @@ mod tests { fn rejects_too_large_inputs() { let witness_map = WitnessMap::from(BTreeMap::from([(Witness(0), FieldElement::from(256u32))])); - let input: FunctionInput = FunctionInput::witness(Witness(0), 8); - assert!(solve_range_opcode(&witness_map, &input, false).is_err()); + let input: FunctionInput = FunctionInput::Witness(Witness(0)); + assert!(solve_range_opcode(&witness_map, &input, 8).is_err()); } #[test] fn accepts_zero_for_zero_bits() { let witness_map = WitnessMap::from(BTreeMap::from([(Witness(0), FieldElement::zero())])); - let input: FunctionInput = FunctionInput::witness(Witness(0), 0); - assert!(solve_range_opcode(&witness_map, &input, false).is_ok()); + let input: FunctionInput = FunctionInput::Witness(Witness(0)); + assert!(solve_range_opcode(&witness_map, &input, 0).is_ok()); } #[test] @@ -56,8 +54,8 @@ mod tests { for value in values { let witness_map = WitnessMap::from(BTreeMap::from([(Witness(0), FieldElement::from(value))])); - let input: FunctionInput = FunctionInput::witness(Witness(0), 8); - assert!(solve_range_opcode(&witness_map, &input, false).is_ok()); + let input: FunctionInput = FunctionInput::Witness(Witness(0)); + assert!(solve_range_opcode(&witness_map, &input, 8).is_ok()); } } } diff --git a/acvm-repo/acvm/src/pwg/blackbox/utils.rs b/acvm-repo/acvm/src/pwg/blackbox/utils.rs index 6c9c5a1025a..2e655523478 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/utils.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/utils.rs @@ -8,7 +8,7 @@ pub(crate) fn to_u8_array( ) -> Result<[u8; N], OpcodeResolutionError> { let mut result = [0; N]; for (it, input) in result.iter_mut().zip(inputs) { - let witness_value_bytes = input_to_value(initial_witness, *input, false)?.to_be_bytes(); + let witness_value_bytes = input_to_value(initial_witness, *input)?.to_be_bytes(); let byte = witness_value_bytes .last() .expect("Field element must be represented by non-zero amount of bytes"); @@ -23,7 +23,7 @@ pub(crate) fn to_u8_vec( ) -> Result, OpcodeResolutionError> { let mut result = Vec::with_capacity(inputs.len()); for input in inputs { - let witness_value_bytes = input_to_value(initial_witness, *input, false)?.to_be_bytes(); + let witness_value_bytes = input_to_value(initial_witness, *input)?.to_be_bytes(); let byte = witness_value_bytes .last() .expect("Field element must be represented by non-zero amount of bytes"); diff --git a/acvm-repo/acvm/src/pwg/mod.rs b/acvm-repo/acvm/src/pwg/mod.rs index e116630bcb6..d492e638946 100644 --- a/acvm-repo/acvm/src/pwg/mod.rs +++ b/acvm-repo/acvm/src/pwg/mod.rs @@ -8,18 +8,14 @@ use acir::{ circuit::{ AssertionPayload, ErrorSelector, ExpressionOrMemory, Opcode, OpcodeLocation, brillig::{BrilligBytecode, BrilligFunctionId}, - opcodes::{ - AcirFunctionId, BlockId, ConstantOrWitnessEnum, FunctionInput, InvalidInputBitSize, - }, + opcodes::{AcirFunctionId, BlockId, FunctionInput, InvalidInputBitSize}, }, native_types::{Expression, Witness, WitnessMap}, }; use acvm_blackbox_solver::BlackBoxResolutionError; use brillig_vm::BranchToFeatureMap; -use self::{ - arithmetic::ExpressionSolver, blackbox::bigint::AcvmBigIntSolver, memory_op::MemoryOpSolver, -}; +use self::{arithmetic::ExpressionSolver, memory_op::MemoryOpSolver}; use crate::BlackBoxFunctionSolver; use thiserror::Error; @@ -213,8 +209,6 @@ pub struct ACVM<'a, F: AcirField, B: BlackBoxFunctionSolver> { /// Stores the solver for memory operations acting on blocks of memory disambiguated by [block][`BlockId`]. block_solvers: HashMap>, - bigint_solver: AcvmBigIntSolver, - /// A list of opcodes which are to be executed by the ACVM. opcodes: &'a [Opcode], /// Index of the next opcode to be executed. @@ -260,12 +254,10 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { assertion_payloads: &'a [(OpcodeLocation, AssertionPayload)], ) -> Self { let status = if opcodes.is_empty() { ACVMStatus::Solved } else { ACVMStatus::InProgress }; - let bigint_solver = AcvmBigIntSolver::with_pedantic_solving(backend.pedantic_solving()); ACVM { status, backend, block_solvers: HashMap::default(), - bigint_solver, opcodes, instruction_pointer: 0, witness_map: initial_witness, @@ -426,22 +418,19 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { let opcode = &self.opcodes[self.instruction_pointer]; let resolution = match opcode { Opcode::AssertZero(expr) => ExpressionSolver::solve(&mut self.witness_map, expr), - Opcode::BlackBoxFuncCall(bb_func) => blackbox::solve( - self.backend, - &mut self.witness_map, - bb_func, - &mut self.bigint_solver, - ), + Opcode::BlackBoxFuncCall(bb_func) => { + blackbox::solve(self.backend, &mut self.witness_map, bb_func) + } Opcode::MemoryInit { block_id, init, .. } => { let solver = self.block_solvers.entry(*block_id).or_default(); solver.init(init, &self.witness_map) } - Opcode::MemoryOp { block_id, op, predicate } => { + Opcode::MemoryOp { block_id, op } => { let solver = self.block_solvers.entry(*block_id).or_default(); solver.solve_memory_op( op, &mut self.witness_map, - predicate, + &None, self.backend.pedantic_solving(), ) } @@ -758,27 +747,33 @@ pub fn witness_to_value( pub fn input_to_value( initial_witness: &WitnessMap, input: FunctionInput, - skip_bitsize_checks: bool, ) -> Result> { - match input.input() { - ConstantOrWitnessEnum::Witness(witness) => { + match input { + FunctionInput::Witness(witness) => { let initial_value = *witness_to_value(initial_witness, witness)?; - if skip_bitsize_checks || initial_value.num_bits() <= input.num_bits() { - Ok(initial_value) - } else { - let value_num_bits = initial_value.num_bits(); - let value = initial_value.to_string(); - Err(OpcodeResolutionError::InvalidInputBitSize { - opcode_location: ErrorLocation::Unresolved, - invalid_input_bit_size: InvalidInputBitSize { - value, - value_num_bits, - max_bits: input.num_bits(), - }, - }) - } + Ok(initial_value) } - ConstantOrWitnessEnum::Constant(value) => Ok(value), + FunctionInput::Constant(value) => Ok(value), + } +} + +pub fn check_bit_size( + value: F, + num_bits: u32, +) -> Result<(), OpcodeResolutionError> { + if value.num_bits() <= num_bits { + Ok(()) + } else { + let value_num_bits = value.num_bits(); + let value = value.to_string(); + Err(OpcodeResolutionError::InvalidInputBitSize { + opcode_location: ErrorLocation::Unresolved, + invalid_input_bit_size: InvalidInputBitSize { + value, + value_num_bits, + max_bits: num_bits, + }, + }) } } diff --git a/acvm-repo/acvm/tests/solver.rs b/acvm-repo/acvm/tests/solver.rs index 6071832e20b..64c50002710 100644 --- a/acvm-repo/acvm/tests/solver.rs +++ b/acvm-repo/acvm/tests/solver.rs @@ -1,6 +1,7 @@ -use std::collections::{BTreeMap, HashSet}; +use std::collections::BTreeMap; use std::sync::Arc; +use acir::InvalidInputBitSize; use acir::brillig::{BitSize, HeapVector, IntegerBitSize}; use acir::{ AcirField, FieldElement, @@ -15,7 +16,7 @@ use acir::{ }; use acvm::pwg::{ACVM, ACVMStatus, ErrorLocation, ForeignCallWaitInfo, OpcodeResolutionError}; -use acvm_blackbox_solver::{BigIntSolver, StubbedBlackBoxSolver}; +use acvm_blackbox_solver::StubbedBlackBoxSolver; use bn254_blackbox_solver::{Bn254BlackBoxSolver, POSEIDON2_CONFIG, field_from_hex}; use brillig_vm::brillig::HeapValueType; @@ -23,7 +24,6 @@ use num_bigint::BigUint; use proptest::arbitrary::any; use proptest::prelude::*; use proptest::result::maybe_ok; -use proptest::sample::select; #[test] fn bls12_381_circuit() { @@ -128,6 +128,7 @@ fn inversion_brillig_oracle_equivalence() { let three_usize = MemoryAddress::direct(5); let brillig_bytecode = BrilligBytecode { + function_name: "invert".to_string(), bytecode: vec![ BrilligOpcode::Const { destination: zero_usize, @@ -280,6 +281,7 @@ fn double_inversion_brillig_oracle() { }; let brillig_bytecode = BrilligBytecode { + function_name: "double_inversion".to_string(), bytecode: vec![ BrilligOpcode::Const { destination: zero_usize, @@ -404,6 +406,7 @@ fn oracle_dependent_execution() { let four_usize = MemoryAddress::direct(6); let brillig_bytecode = BrilligBytecode { + function_name: "double_inverse".to_string(), bytecode: vec![ BrilligOpcode::Const { destination: zero_usize, @@ -547,6 +550,7 @@ fn brillig_oracle_predicate() { }; let brillig_bytecode = BrilligBytecode { + function_name: "inverse".to_string(), bytecode: vec![ BrilligOpcode::Const { destination: MemoryAddress::direct(0), @@ -695,6 +699,7 @@ fn unsatisfied_opcode_resolved_brillig() { }; let brillig_bytecode = BrilligBytecode { + function_name: "equality_check".to_string(), bytecode: vec![ BrilligOpcode::Const { destination: MemoryAddress::direct(0), @@ -794,11 +799,8 @@ fn memory_operations() { block_type: BlockType::Memory, }; - let read_op = Opcode::MemoryOp { - block_id, - op: MemOp::read_at_mem_index(Witness(6).into(), Witness(7)), - predicate: None, - }; + let read_op = + Opcode::MemoryOp { block_id, op: MemOp::read_at_mem_index(Witness(6).into(), Witness(7)) }; let expression = Opcode::AssertZero(Expression { mul_terms: Vec::new(), @@ -825,8 +827,8 @@ fn memory_operations() { type ConstantOrWitness = (FieldElement, bool); // For each ConstantOrWitness, -// - If use_constant, then convert to a FunctionInput::constant -// - Otherwise, convert to FunctionInput::witness +// - If use_constant, then convert to a FunctionInput::Constant +// - Otherwise, convert to FunctionInput::Witness // + With the Witness index as (input_index + offset) fn constant_or_witness_to_function_inputs( xs: Vec, @@ -838,9 +840,19 @@ fn constant_or_witness_to_function_inputs( .enumerate() .map(|(i, (x, use_constant))| { if use_constant { - FunctionInput::constant(x, num_bits).map_err(From::from) + if x.num_bits() > num_bits { + return Err(OpcodeResolutionError::InvalidInputBitSize { + opcode_location: ErrorLocation::Unresolved, + invalid_input_bit_size: InvalidInputBitSize { + value: x.to_string(), + value_num_bits: x.num_bits(), + max_bits: num_bits, + }, + }); + } + Ok(FunctionInput::Constant(x)) } else { - Ok(FunctionInput::witness(Witness((i + offset) as u32), num_bits)) + Ok(FunctionInput::Witness(Witness((i + offset) as u32))) } }) .collect() @@ -856,11 +868,6 @@ fn drop_use_constant_eq(x: &[ConstantOrWitness], y: &[ConstantOrWitness]) -> boo drop_use_constant(x) == drop_use_constant(y) } -// Convert FieldElement's to ConstantOrWitness's by making all of them witnesses -fn use_witnesses(inputs: Vec) -> Vec { - inputs.into_iter().map(|input| (input, false)).collect() -} - fn solve_array_input_blackbox_call( inputs: Vec, num_outputs: usize, @@ -896,154 +903,20 @@ where .collect()) } -prop_compose! { - fn bigint_with_modulus()(modulus in select(BigIntSolver::allowed_bigint_moduli())) - (inputs in proptest::collection::vec(any::<(u8, bool)>(), modulus.len()), modulus in Just(modulus)) - -> (Vec, Vec) { - let inputs = inputs.into_iter().zip(modulus.iter()).map(|((input, use_constant), modulus_byte)| { - (FieldElement::from(u128::from(input.clamp(0, *modulus_byte))), use_constant) - }).collect(); - (inputs, modulus) - } -} - -prop_compose! { - fn bigint_pair_with_modulus()(inputs_modulus in bigint_with_modulus()) - (second_inputs in proptest::collection::vec(any::<(u8, bool)>(), inputs_modulus.1.len()), inputs_modulus in Just(inputs_modulus)) - -> (Vec, Vec, Vec) { - let (inputs, modulus) = inputs_modulus; - let second_inputs = second_inputs.into_iter().zip(modulus.iter()).map(|((input, use_constant), modulus_byte)| { - (FieldElement::from(u128::from(input.clamp(0, *modulus_byte))), use_constant) - }).collect(); - (inputs, second_inputs, modulus) - } -} - -prop_compose! { - fn bigint_triple_with_modulus()(inputs_pair_modulus in bigint_pair_with_modulus()) - (third_inputs in proptest::collection::vec(any::<(u8, bool)>(), inputs_pair_modulus.2.len()), inputs_pair_modulus in Just(inputs_pair_modulus)) - -> (Vec, Vec, Vec, Vec) { - let (inputs, second_inputs, modulus) = inputs_pair_modulus; - let third_inputs = third_inputs.into_iter().zip(modulus.iter()).map(|((input, use_constant), modulus_byte)| { - (FieldElement::from(u128::from(input.clamp(0, *modulus_byte))), use_constant) - }).collect(); - (inputs, second_inputs, third_inputs, modulus) - } -} - -fn bigint_add_op() -> BlackBoxFuncCall { - BlackBoxFuncCall::BigIntAdd { lhs: 0, rhs: 1, output: 2 } -} - -fn bigint_mul_op() -> BlackBoxFuncCall { - BlackBoxFuncCall::BigIntMul { lhs: 0, rhs: 1, output: 2 } -} - -fn bigint_sub_op() -> BlackBoxFuncCall { - BlackBoxFuncCall::BigIntSub { lhs: 0, rhs: 1, output: 2 } -} - -fn bigint_div_op() -> BlackBoxFuncCall { - BlackBoxFuncCall::BigIntDiv { lhs: 0, rhs: 1, output: 2 } -} - -// Input is a BigInt, represented as a LE Vec of u8-range FieldElement's along -// with their use_constant values. -// -// Output is a zeroed BigInt that matches the input BigInt's -// - Byte length -// - use_constant values -fn bigint_zeroed(inputs: &[ConstantOrWitness]) -> Vec { - inputs.iter().map(|(_, use_constant)| (FieldElement::zero(), *use_constant)).collect() -} - -// bigint_zeroed, but returns one -fn bigint_to_one(inputs: &[ConstantOrWitness]) -> Vec { - let mut one = bigint_zeroed(inputs); - // little-endian - one[0] = (FieldElement::one(), one[0].1); - one -} - -// Using the given BigInt modulus, solve the following circuit: -// - Convert xs, ys to BigInt's with ID's 0, 1, resp. -// - If the middle_op is present, run it -// + Input BigInt ID's: 0, 1 -// + Output BigInt ID: 2 -// - If the middle_op is missing, the output BigInt ID is 0 -// - Run BigIntToLeBytes on the output BigInt ID -// - Output the resulting Vec of LE bytes -fn bigint_solve_binary_op_opt( - middle_op: Option>, - modulus: Vec, - lhs: Vec, - rhs: Vec, - pedantic_solving: bool, -) -> Result, OpcodeResolutionError> { - let solver = StubbedBlackBoxSolver(pedantic_solving); - let initial_witness_vec: Vec<_> = lhs - .iter() - .chain(rhs.iter()) - .enumerate() - .map(|(i, (x, _))| (Witness(i as u32), *x)) - .collect(); - let output_witnesses: Vec<_> = initial_witness_vec - .iter() - .take(lhs.len()) - .enumerate() - .map(|(index, _)| Witness((index + 2 * lhs.len()) as u32)) // offset past the indices of lhs, rhs - .collect(); - let initial_witness = WitnessMap::from(BTreeMap::from_iter(initial_witness_vec)); - - let lhs = constant_or_witness_to_function_inputs(lhs, 0, None)?; - let rhs = constant_or_witness_to_function_inputs(rhs, lhs.len(), None)?; - - let to_op_input = if middle_op.is_some() { 2 } else { 0 }; - - let bigint_from_lhs_op = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::BigIntFromLeBytes { - inputs: lhs, - modulus: modulus.clone(), - output: 0, - }); - let bigint_from_rhs_op = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::BigIntFromLeBytes { - inputs: rhs, - modulus: modulus.clone(), - output: 1, - }); - let bigint_to_op = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::BigIntToLeBytes { - input: to_op_input, - outputs: output_witnesses.clone(), - }); - - let mut opcodes = vec![bigint_from_lhs_op, bigint_from_rhs_op]; - if let Some(middle_op) = middle_op { - opcodes.push(Opcode::BlackBoxFuncCall(middle_op)); - } - opcodes.push(bigint_to_op); - - let unconstrained_functions = vec![]; - let mut acvm = ACVM::new(&solver, &opcodes, initial_witness, &unconstrained_functions, &[]); - let solver_status = acvm.solve(); - assert_eq!(solver_status, ACVMStatus::Solved); - let witness_map = acvm.finalize(); - Ok(output_witnesses - .iter() - .map(|witness| *witness_map.get(witness).expect("all witnesses to be set")) - .collect()) -} - // Solve the given BlackBoxFuncCall with witnesses: 1, 2 as x, y, resp. #[cfg(test)] fn solve_blackbox_func_call( blackbox_func_call: impl Fn( Option, Option, + Option, ) -> Result< BlackBoxFuncCall, OpcodeResolutionError, >, lhs: (FieldElement, bool), // if false, use a Witness rhs: (FieldElement, bool), // if false, use a Witness + num_bits: Option, ) -> Result> { let solver = StubbedBlackBoxSolver::default(); let (lhs, lhs_constant) = lhs; @@ -1062,7 +935,7 @@ fn solve_blackbox_func_call( rhs_opt = Some(rhs); } - let op = Opcode::BlackBoxFuncCall(blackbox_func_call(lhs_opt, rhs_opt)?); + let op = Opcode::BlackBoxFuncCall(blackbox_func_call(lhs_opt, rhs_opt, num_bits)?); let opcodes = vec![op]; let unconstrained_functions = vec![]; let mut acvm = ACVM::new(&solver, &opcodes, initial_witness, &unconstrained_functions, &[]); @@ -1115,18 +988,7 @@ fn poseidon2_permutation_op( function_inputs_and_outputs: (Vec>, Vec), ) -> Result, OpcodeResolutionError> { let (inputs, outputs) = function_inputs_and_outputs; - let len = inputs.len() as u32; - Ok(BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs, len }) -} - -// N inputs -// N outputs -fn poseidon2_permutation_invalid_len_op( - function_inputs_and_outputs: (Vec>, Vec), -) -> Result, OpcodeResolutionError> { - let (inputs, outputs) = function_inputs_and_outputs; - let len = (inputs.len() as u32) + 1; - Ok(BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs, len }) + Ok(BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs }) } // 24 inputs (16 + 8) @@ -1224,120 +1086,69 @@ fn run_both_poseidon2_permutations( Ok((into_repr_vec(result), expected_result.into_iter().map(into_new_ark_field).collect())) } -// Using the given BigInt modulus, solve the following circuit: -// - Convert xs, ys to BigInt's with ID's 0, 1, resp. -// - Run the middle_op: -// + Input BigInt ID's: 0, 1 -// + Output BigInt ID: 2 -// - Run BigIntToLeBytes on the output BigInt ID -// - Output the resulting Vec of LE bytes -fn bigint_solve_binary_op( - middle_op: BlackBoxFuncCall, - modulus: Vec, - lhs: Vec, - rhs: Vec, - pedantic_solving: bool, -) -> Vec { - bigint_solve_binary_op_opt(Some(middle_op), modulus, lhs, rhs, pedantic_solving).unwrap() -} - -// Using the given BigInt modulus, solve the following circuit: -// - Convert the input to a BigInt with ID 0 -// - Run BigIntToLeBytes on BigInt ID 0 -// - Output the resulting Vec of LE bytes -fn bigint_solve_from_to_le_bytes( - modulus: Vec, - inputs: Vec, - pedantic_solving: bool, -) -> Vec { - bigint_solve_binary_op_opt(None, modulus, inputs, vec![], pedantic_solving).unwrap() -} - -// Test bigint_solve_from_to_le_bytes with a guaranteed-invalid modulus -// and optional pedantic_solving -fn bigint_from_to_le_bytes_disallowed_modulus_helper( - modulus: &mut Vec, - patch_location: usize, - patch_amount: u8, - zero_or_ones_constant: bool, - use_constant: bool, - pedantic_solving: bool, -) -> (Vec, Vec) { - let allowed_moduli: HashSet> = - BigIntSolver::allowed_bigint_moduli().into_iter().collect(); - let mut patch_location = patch_location % modulus.len(); - let patch_amount = patch_amount.clamp(1, u8::MAX); - while allowed_moduli.contains(modulus) { - modulus[patch_location] = patch_amount.wrapping_add(modulus[patch_location]); - patch_location += 1; - patch_location %= modulus.len(); - } - - let zero_function_input = - if zero_or_ones_constant { FieldElement::zero() } else { FieldElement::one() }; - let zero: Vec<_> = modulus.iter().map(|_| (zero_function_input, use_constant)).collect(); - let expected_results: Vec<_> = drop_use_constant(&zero); - let results = bigint_solve_from_to_le_bytes(modulus.clone(), zero, pedantic_solving); - - (results, expected_results) -} - fn function_input_from_option( witness: Witness, opt_constant: Option, ) -> Result, OpcodeResolutionError> { opt_constant - .map(|constant| { - FunctionInput::constant(constant, FieldElement::max_num_bits()).map_err(From::from) - }) - .unwrap_or(Ok(FunctionInput::witness(witness, FieldElement::max_num_bits()))) + .map(|constant| Ok(FunctionInput::Constant(constant))) + .unwrap_or(Ok(FunctionInput::Witness(witness))) } fn and_op( x: Option, y: Option, + num_bits: Option, ) -> Result, OpcodeResolutionError> { let lhs = function_input_from_option(Witness(1), x)?; let rhs = function_input_from_option(Witness(2), y)?; - Ok(BlackBoxFuncCall::AND { lhs, rhs, output: Witness(3) }) + Ok(BlackBoxFuncCall::AND { lhs, rhs, num_bits: num_bits.unwrap(), output: Witness(3) }) } fn xor_op( x: Option, y: Option, + num_bits: Option, ) -> Result, OpcodeResolutionError> { let lhs = function_input_from_option(Witness(1), x)?; let rhs = function_input_from_option(Witness(2), y)?; - Ok(BlackBoxFuncCall::XOR { lhs, rhs, output: Witness(3) }) + Ok(BlackBoxFuncCall::XOR { lhs, rhs, num_bits: num_bits.unwrap(), output: Witness(3) }) } fn prop_assert_commutative( op: impl Fn( Option, Option, + Option, ) -> Result, OpcodeResolutionError>, x: (FieldElement, bool), y: (FieldElement, bool), + num_bits: Option, ) -> (FieldElement, FieldElement) { - (solve_blackbox_func_call(&op, x, y).unwrap(), solve_blackbox_func_call(&op, y, x).unwrap()) + ( + solve_blackbox_func_call(&op, x, y, num_bits).unwrap(), + solve_blackbox_func_call(&op, y, x, num_bits).unwrap(), + ) } fn prop_assert_associative( op: impl Fn( Option, Option, + Option, ) -> Result, OpcodeResolutionError>, x: (FieldElement, bool), y: (FieldElement, bool), z: (FieldElement, bool), use_constant_xy: bool, use_constant_yz: bool, + num_bits: Option, ) -> (FieldElement, FieldElement) { - let f_xy = (solve_blackbox_func_call(&op, x, y).unwrap(), use_constant_xy); - let f_f_xy_z = solve_blackbox_func_call(&op, f_xy, z).unwrap(); + let f_xy = (solve_blackbox_func_call(&op, x, y, num_bits).unwrap(), use_constant_xy); + let f_f_xy_z = solve_blackbox_func_call(&op, f_xy, z, num_bits).unwrap(); - let f_yz = (solve_blackbox_func_call(&op, y, z).unwrap(), use_constant_yz); - let f_x_f_yz = solve_blackbox_func_call(&op, x, f_yz).unwrap(); + let f_yz = (solve_blackbox_func_call(&op, y, z, num_bits).unwrap(), use_constant_yz); + let f_x_f_yz = solve_blackbox_func_call(&op, x, f_yz, num_bits).unwrap(); (f_f_xy_z, f_x_f_yz) } @@ -1346,22 +1157,26 @@ fn prop_assert_identity_l( op: impl Fn( Option, Option, + Option, ) -> Result, OpcodeResolutionError>, op_identity: (FieldElement, bool), x: (FieldElement, bool), + num_bits: Option, ) -> (FieldElement, FieldElement) { - (solve_blackbox_func_call(op, op_identity, x).unwrap(), x.0) + (solve_blackbox_func_call(op, op_identity, x, num_bits).unwrap(), x.0) } fn prop_assert_zero_l( op: impl Fn( Option, Option, + Option, ) -> Result, OpcodeResolutionError>, op_zero: (FieldElement, bool), x: (FieldElement, bool), + num_bits: Option, ) -> (FieldElement, FieldElement) { - (solve_blackbox_func_call(op, op_zero, x).unwrap(), FieldElement::zero()) + (solve_blackbox_func_call(op, op_zero, x, num_bits).unwrap(), FieldElement::zero()) } // Test that varying one of the inputs produces a different result @@ -1576,46 +1391,74 @@ proptest! { #[test] fn and_commutative(x in field_element(), y in field_element()) { - let (lhs, rhs) = prop_assert_commutative(and_op, x, y); + let max_num_bits = if y.0.num_bits() > x.0.num_bits() { + y.0.num_bits() + } else { + x.0.num_bits() + }; + let (lhs, rhs) = prop_assert_commutative(and_op, x, y, Some(max_num_bits)); prop_assert_eq!(lhs, rhs); } #[test] fn xor_commutative(x in field_element(), y in field_element()) { - let (lhs, rhs) = prop_assert_commutative(xor_op, x, y); + let max_num_bits = if y.0.num_bits() > x.0.num_bits() { + y.0.num_bits() + } else { + x.0.num_bits() + }; + let (lhs, rhs) = prop_assert_commutative(xor_op, x, y,Some(max_num_bits)); prop_assert_eq!(lhs, rhs); } #[test] fn and_associative(x in field_element(), y in field_element(), z in field_element(), use_constant_xy: bool, use_constant_yz: bool) { - let (lhs, rhs) = prop_assert_associative(and_op, x, y, z, use_constant_xy, use_constant_yz); + let mut num_bits = if y.0.num_bits() > x.0.num_bits() { + y.0.num_bits() + } else { + x.0.num_bits() + }; + if num_bits < z.0.num_bits() { + num_bits = z.0.num_bits(); + } + let (lhs, rhs) = prop_assert_associative(and_op, x, y, z, use_constant_xy, use_constant_yz, Some(num_bits)); prop_assert_eq!(lhs, rhs); } #[test] // TODO(https://github.com/noir-lang/noir/issues/5638) - #[should_panic(expected = "assertion failed: `(left == right)`")] + #[should_panic(expected = "assertion `left == right` failed")] fn xor_associative(x in field_element(), y in field_element(), z in field_element(), use_constant_xy: bool, use_constant_yz: bool) { - let (lhs, rhs) = prop_assert_associative(xor_op, x, y, z, use_constant_xy, use_constant_yz); + let max_num_bits = if y.0.num_bits() > x.0.num_bits() { + y.0.num_bits() + } else { + x.0.num_bits() + }; + let (lhs, rhs) = prop_assert_associative(xor_op, x, y, z, use_constant_xy, use_constant_yz, Some(max_num_bits)); prop_assert_eq!(lhs, rhs); } // test that AND(x, x) == x #[test] fn and_self_identity(x in field_element()) { - prop_assert_eq!(solve_blackbox_func_call(and_op, x, x).unwrap(), x.0); + prop_assert_eq!(solve_blackbox_func_call(and_op, x, x, Some(x.0.num_bits())).unwrap(), x.0); } // test that XOR(x, x) == 0 #[test] fn xor_self_zero(x in field_element()) { - prop_assert_eq!(solve_blackbox_func_call(xor_op, x, x).unwrap(), FieldElement::zero()); + prop_assert_eq!(solve_blackbox_func_call(xor_op, x, x, Some(x.0.num_bits())).unwrap(), FieldElement::zero()); } #[test] fn and_identity_l(x in field_element(), ones_constant: bool) { let ones = (field_element_ones(), ones_constant); - let (lhs, rhs) = prop_assert_identity_l(and_op, ones, x); + let max_num_bits = if x.0.num_bits() > ones.0.num_bits() { + x.0.num_bits() + } else { + ones.0.num_bits() + }; + let (lhs, rhs) = prop_assert_identity_l(and_op, ones, x, Some(max_num_bits)); if x <= ones { prop_assert_eq!(lhs, rhs); } else { @@ -1626,14 +1469,14 @@ proptest! { #[test] fn xor_identity_l(x in field_element(), zero_constant: bool) { let zero = (FieldElement::zero(), zero_constant); - let (lhs, rhs) = prop_assert_identity_l(xor_op, zero, x); + let (lhs, rhs) = prop_assert_identity_l(xor_op, zero, x, Some(x.0.num_bits())); prop_assert_eq!(lhs, rhs); } #[test] fn and_zero_l(x in field_element(), ones_constant: bool) { let zero = (FieldElement::zero(), ones_constant); - let (lhs, rhs) = prop_assert_zero_l(and_op, zero, x); + let (lhs, rhs) = prop_assert_zero_l(and_op, zero, x, Some(x.0.num_bits())); prop_assert_eq!(lhs, rhs); } @@ -1682,324 +1525,12 @@ proptest! { // TODO(https://github.com/noir-lang/noir/issues/5699): wrong failure message #[test] - #[should_panic(expected = "Failure(BlackBoxFunctionFailed(Poseidon2Permutation, \"the number of inputs does not match specified length. 6 != 7\"))")] + #[should_panic(expected = "Failure(BlackBoxFunctionFailed(Poseidon2Permutation, \"the input and output sizes are not consistent. 6 != 1\"))")] fn poseidon2_permutation_invalid_size_fails(inputs_distinct_inputs in any_distinct_inputs(None, 6, 6)) { let (inputs, distinct_inputs) = inputs_distinct_inputs; let pedantic_solving = true; - let (result, message) = prop_assert_injective(inputs, distinct_inputs, 1, None, pedantic_solving, poseidon2_permutation_invalid_len_op); + let (result, message) = prop_assert_injective(inputs, distinct_inputs, 1, None, pedantic_solving, poseidon2_permutation_op); prop_assert!(result, "{}", message); } - #[test] - fn bigint_from_to_le_bytes_zero_one(modulus in select(BigIntSolver::allowed_bigint_moduli()), zero_or_ones_constant: bool, use_constant: bool) { - let zero_function_input = if zero_or_ones_constant { - FieldElement::one() - } else { - FieldElement::zero() - }; - let zero_or_ones: Vec<_> = modulus.iter().map(|_| (zero_function_input, use_constant)).collect(); - let expected_results = drop_use_constant(&zero_or_ones); - let pedantic_solving = true; - let results = bigint_solve_from_to_le_bytes(modulus.clone(), zero_or_ones, pedantic_solving); - prop_assert_eq!(results, expected_results); - } - - #[test] - fn bigint_from_to_le_bytes((input, modulus) in bigint_with_modulus()) { - let expected_results: Vec<_> = drop_use_constant(&input); - let pedantic_solving = true; - let results = bigint_solve_from_to_le_bytes(modulus.clone(), input, pedantic_solving); - prop_assert_eq!(results, expected_results); - } - - #[test] - // TODO(https://github.com/noir-lang/noir/issues/5580): desired behavior? - fn bigint_from_to_le_bytes_extra_input_bytes((mut input, modulus) in bigint_with_modulus(), extra_bytes_len: u8, extra_bytes in proptest::collection::vec(any::<(u8, bool)>(), u8::MAX as usize)) { - let mut extra_bytes: Vec<_> = extra_bytes - .into_iter() - .take(extra_bytes_len as usize) - .map(|(x, use_constant)| (FieldElement::from(u128::from(x)), use_constant)) - .collect(); - input.append(&mut extra_bytes); - let expected_results: Vec<_> = drop_use_constant(&input); - let pedantic_solving = false; - let results = bigint_solve_from_to_le_bytes(modulus.clone(), input, pedantic_solving); - prop_assert_eq!(results, expected_results); - } - - #[test] - #[should_panic(expected = "--pedantic-solving: bigint_from_bytes: inputs.len() > modulus.len()")] - fn bigint_from_to_le_bytes_extra_input_bytes_with_pedantic((mut input, modulus) in bigint_with_modulus(), extra_bytes_len: u8, extra_bytes in proptest::collection::vec(any::<(u8, bool)>(), u8::MAX as usize)) { - let mut extra_bytes: Vec<_> = extra_bytes - .into_iter() - .take(extra_bytes_len as usize) - .map(|(x, use_constant)| (FieldElement::from(u128::from(x)), use_constant)) - .collect(); - input.append(&mut extra_bytes); - let expected_results: Vec<_> = drop_use_constant(&input); - let pedantic_solving = true; - let results = bigint_solve_from_to_le_bytes(modulus.clone(), input, pedantic_solving); - prop_assert_eq!(results, expected_results); - } - - #[test] - // TODO(https://github.com/noir-lang/noir/issues/5580): desired behavior? - #[should_panic(expected = "Test failed: assertion failed: `(left == right)`")] - fn bigint_from_to_le_bytes_bigger_than_u8((input, modulus) in bigint_with_modulus(), patch_location: usize, larger_value: u16, use_constant: bool) { - let mut input = input; - let patch_location = patch_location % input.len(); - let larger_value = FieldElement::from(u128::from(std::cmp::max(u16::from(u8::MAX) + 1, larger_value))); - input[patch_location] = (larger_value, use_constant); - let expected_results: Vec<_> = drop_use_constant(&input); - let pedantic_solving = true; - let results = bigint_solve_from_to_le_bytes(modulus.clone(), input, pedantic_solving); - prop_assert_eq!(results, expected_results); - } - - #[test] - // TODO(https://github.com/noir-lang/noir/issues/5578): this test attempts to use a guaranteed-invalid BigInt modulus - // #[should_panic(expected = "attempt to add with overflow")] - fn bigint_from_to_le_bytes_disallowed_modulus(mut modulus in select(BigIntSolver::allowed_bigint_moduli()), patch_location: usize, patch_amount: u8, zero_or_ones_constant: bool, use_constant: bool) { - let pedantic_solving = false; - let (results, expected_results) = bigint_from_to_le_bytes_disallowed_modulus_helper( - &mut modulus, - patch_location, - patch_amount, - zero_or_ones_constant, - use_constant, - pedantic_solving, - ); - prop_assert_eq!(results, expected_results); - } - - #[test] - #[should_panic(expected = "--pedantic-solving: bigint_from_bytes: disallowed modulus [")] - fn bigint_from_to_le_bytes_disallowed_modulus_panics_with_pedantic(mut modulus in select(BigIntSolver::allowed_bigint_moduli()), patch_location: usize, patch_amount: u8, zero_or_ones_constant: bool, use_constant: bool) { - let pedantic_solving = true; - let (results, expected_results) = bigint_from_to_le_bytes_disallowed_modulus_helper( - &mut modulus, - patch_location, - patch_amount, - zero_or_ones_constant, - use_constant, - pedantic_solving, - ); - prop_assert_eq!(results, expected_results); - } - - #[test] - fn bigint_add_commutative((xs, ys, modulus) in bigint_pair_with_modulus()) { - let pedantic_solving = true; - let lhs_results = bigint_solve_binary_op(bigint_add_op(), modulus.clone(), xs.clone(), ys.clone(), pedantic_solving); - let rhs_results = bigint_solve_binary_op(bigint_add_op(), modulus, ys, xs, pedantic_solving); - - prop_assert_eq!(lhs_results, rhs_results); - } - - #[test] - fn bigint_mul_commutative((xs, ys, modulus) in bigint_pair_with_modulus()) { - let pedantic_solving = true; - let lhs_results = bigint_solve_binary_op(bigint_mul_op(), modulus.clone(), xs.clone(), ys.clone(), pedantic_solving); - let rhs_results = bigint_solve_binary_op(bigint_mul_op(), modulus, ys, xs, pedantic_solving); - - prop_assert_eq!(lhs_results, rhs_results); - } - - #[test] - fn bigint_add_associative((xs, ys, zs, modulus) in bigint_triple_with_modulus()) { - let pedantic_solving = true; - - // f(f(xs, ys), zs) == - let op_xs_ys = bigint_solve_binary_op(bigint_add_op(), modulus.clone(), xs.clone(), ys.clone(), pedantic_solving); - let xs_ys = use_witnesses(op_xs_ys); - let op_xs_ys_op_zs = bigint_solve_binary_op(bigint_add_op(), modulus.clone(), xs_ys, zs.clone(), pedantic_solving); - - // f(xs, f(ys, zs)) - let op_ys_zs = bigint_solve_binary_op(bigint_add_op(), modulus.clone(), ys.clone(), zs.clone(), pedantic_solving); - let ys_zs = use_witnesses(op_ys_zs); - let op_xs_op_ys_zs = bigint_solve_binary_op(bigint_add_op(), modulus, xs, ys_zs, pedantic_solving); - - prop_assert_eq!(op_xs_ys_op_zs, op_xs_op_ys_zs); - } - - #[test] - fn bigint_mul_associative((xs, ys, zs, modulus) in bigint_triple_with_modulus()) { - let pedantic_solving = true; - - // f(f(xs, ys), zs) == - let op_xs_ys = bigint_solve_binary_op(bigint_mul_op(), modulus.clone(), xs.clone(), ys.clone(), pedantic_solving); - let xs_ys = use_witnesses(op_xs_ys); - let op_xs_ys_op_zs = bigint_solve_binary_op(bigint_mul_op(), modulus.clone(), xs_ys, zs.clone(), pedantic_solving); - - // f(xs, f(ys, zs)) - let op_ys_zs = bigint_solve_binary_op(bigint_mul_op(), modulus.clone(), ys.clone(), zs.clone(), pedantic_solving); - let ys_zs = use_witnesses(op_ys_zs); - let op_xs_op_ys_zs = bigint_solve_binary_op(bigint_mul_op(), modulus, xs, ys_zs, pedantic_solving); - - prop_assert_eq!(op_xs_ys_op_zs, op_xs_op_ys_zs); - } - - #[test] - fn bigint_mul_add_distributive((xs, ys, zs, modulus) in bigint_triple_with_modulus()) { - let pedantic_solving = true; - - // xs * (ys + zs) == - let add_ys_zs = bigint_solve_binary_op(bigint_add_op(), modulus.clone(), ys.clone(), zs.clone(), pedantic_solving); - let add_ys_zs = use_witnesses(add_ys_zs); - let mul_xs_add_ys_zs = bigint_solve_binary_op(bigint_mul_op(), modulus.clone(), xs.clone(), add_ys_zs, pedantic_solving); - - // xs * ys + xs * zs - let mul_xs_ys = bigint_solve_binary_op(bigint_mul_op(), modulus.clone(), xs.clone(), ys, pedantic_solving); - let mul_xs_ys = use_witnesses(mul_xs_ys); - let mul_xs_zs = bigint_solve_binary_op(bigint_mul_op(), modulus.clone(), xs, zs, pedantic_solving); - let mul_xs_zs = use_witnesses(mul_xs_zs); - let add_mul_xs_ys_mul_xs_zs = bigint_solve_binary_op(bigint_add_op(), modulus, mul_xs_ys, mul_xs_zs, pedantic_solving); - - prop_assert_eq!(mul_xs_add_ys_zs, add_mul_xs_ys_mul_xs_zs); - } - - - #[test] - fn bigint_add_zero_l((xs, modulus) in bigint_with_modulus()) { - let zero = bigint_zeroed(&xs); - let expected_results = drop_use_constant(&xs); - let pedantic_solving = true; - let results = bigint_solve_binary_op(bigint_add_op(), modulus, zero, xs, pedantic_solving); - - prop_assert_eq!(results, expected_results); - } - - #[test] - fn bigint_mul_zero_l((xs, modulus) in bigint_with_modulus()) { - let zero = bigint_zeroed(&xs); - let expected_results = drop_use_constant(&zero); - let pedantic_solving = true; - let results = bigint_solve_binary_op(bigint_mul_op(), modulus, zero, xs, pedantic_solving); - prop_assert_eq!(results, expected_results); - } - - #[test] - fn bigint_mul_one_l((xs, modulus) in bigint_with_modulus()) { - let one = bigint_to_one(&xs); - let expected_results: Vec<_> = drop_use_constant(&xs); - let pedantic_solving = true; - let results = bigint_solve_binary_op(bigint_mul_op(), modulus, one, xs, pedantic_solving); - prop_assert_eq!(results, expected_results); - } - - #[test] - fn bigint_sub_self((xs, modulus) in bigint_with_modulus()) { - let expected_results = drop_use_constant(&bigint_zeroed(&xs)); - let pedantic_solving = true; - let results = bigint_solve_binary_op(bigint_sub_op(), modulus, xs.clone(), xs, pedantic_solving); - prop_assert_eq!(results, expected_results); - } - - #[test] - fn bigint_sub_zero((xs, modulus) in bigint_with_modulus()) { - let zero = bigint_zeroed(&xs); - let expected_results: Vec<_> = drop_use_constant(&xs); - let pedantic_solving = true; - let results = bigint_solve_binary_op(bigint_sub_op(), modulus, xs, zero, pedantic_solving); - prop_assert_eq!(results, expected_results); - } - - #[test] - fn bigint_sub_one((xs, modulus) in bigint_with_modulus()) { - let one = bigint_to_one(&xs); - let expected_results: Vec<_> = drop_use_constant(&xs); - let pedantic_solving = true; - let results = bigint_solve_binary_op(bigint_sub_op(), modulus, xs, one, pedantic_solving); - prop_assert!(results != expected_results, "{:?} == {:?}", results, expected_results); - } - - #[test] - fn bigint_div_self((xs, modulus) in bigint_with_modulus()) { - let one = drop_use_constant(&bigint_to_one(&xs)); - let pedantic_solving = true; - let results = bigint_solve_binary_op(bigint_div_op(), modulus, xs.clone(), xs, pedantic_solving); - prop_assert_eq!(results, one); - } - - #[test] - // TODO(https://github.com/noir-lang/noir/issues/5645) - fn bigint_div_by_zero((xs, modulus) in bigint_with_modulus()) { - let zero = bigint_zeroed(&xs); - let expected_results = drop_use_constant(&zero); - let pedantic_solving = false; - let results = bigint_solve_binary_op(bigint_div_op(), modulus, xs, zero, pedantic_solving); - prop_assert_eq!(results, expected_results); - } - - #[test] - #[should_panic(expected = "Attempted to divide BigInt by zero")] - fn bigint_div_by_zero_with_pedantic((xs, modulus) in bigint_with_modulus()) { - let zero = bigint_zeroed(&xs); - let expected_results = drop_use_constant(&zero); - let pedantic_solving = true; - let results = bigint_solve_binary_op(bigint_div_op(), modulus, xs, zero, pedantic_solving); - prop_assert_eq!(results, expected_results); - } - - #[test] - fn bigint_div_one((xs, modulus) in bigint_with_modulus()) { - let one = bigint_to_one(&xs); - let expected_results = drop_use_constant(&xs); - let pedantic_solving = true; - let results = bigint_solve_binary_op(bigint_div_op(), modulus, xs, one, pedantic_solving); - prop_assert_eq!(results, expected_results); - } - - #[test] - fn bigint_div_zero((xs, modulus) in bigint_with_modulus()) { - let zero = bigint_zeroed(&xs); - let expected_results = drop_use_constant(&zero); - let pedantic_solving = true; - let results = bigint_solve_binary_op(bigint_div_op(), modulus, zero, xs, pedantic_solving); - prop_assert_eq!(results, expected_results); - } - - #[test] - fn bigint_add_sub((xs, ys, modulus) in bigint_pair_with_modulus()) { - let expected_results = drop_use_constant(&xs); - let pedantic_solving = true; - let add_results = bigint_solve_binary_op(bigint_add_op(), modulus.clone(), xs, ys.clone(), pedantic_solving); - let add_bigint = use_witnesses(add_results); - let results = bigint_solve_binary_op(bigint_sub_op(), modulus, add_bigint, ys, pedantic_solving); - - prop_assert_eq!(results, expected_results); - } - - #[test] - fn bigint_sub_add((xs, ys, modulus) in bigint_pair_with_modulus()) { - let expected_results = drop_use_constant(&xs); - let pedantic_solving = true; - let sub_results = bigint_solve_binary_op(bigint_sub_op(), modulus.clone(), xs, ys.clone(), pedantic_solving); - let add_bigint = use_witnesses(sub_results); - let results = bigint_solve_binary_op(bigint_add_op(), modulus, add_bigint, ys, pedantic_solving); - - prop_assert_eq!(results, expected_results); - } - - #[test] - fn bigint_div_mul((xs, ys, modulus) in bigint_pair_with_modulus()) { - let expected_results = drop_use_constant(&xs); - let pedantic_solving = true; - let div_results = bigint_solve_binary_op(bigint_div_op(), modulus.clone(), xs, ys.clone(), pedantic_solving); - let div_bigint = use_witnesses(div_results); - let results = bigint_solve_binary_op(bigint_mul_op(), modulus, div_bigint, ys, pedantic_solving); - - prop_assert_eq!(results, expected_results); - } - - #[test] - fn bigint_mul_div((xs, ys, modulus) in bigint_pair_with_modulus()) { - let expected_results = drop_use_constant(&xs); - let pedantic_solving = true; - let mul_results = bigint_solve_binary_op(bigint_mul_op(), modulus.clone(), xs, ys.clone(), pedantic_solving); - let mul_bigint = use_witnesses(mul_results); - let results = bigint_solve_binary_op(bigint_div_op(), modulus, mul_bigint, ys, pedantic_solving); - - prop_assert_eq!(results, expected_results); - } } diff --git a/acvm-repo/acvm_js/src/js_execution_error.rs b/acvm-repo/acvm_js/src/js_execution_error.rs index 3a00bf8d79b..3ed59db6e0b 100644 --- a/acvm-repo/acvm_js/src/js_execution_error.rs +++ b/acvm-repo/acvm_js/src/js_execution_error.rs @@ -1,5 +1,5 @@ use acvm::{ - FieldElement, + AcirField, FieldElement, acir::circuit::{OpcodeLocation, brillig::BrilligFunctionId, opcodes::AcirFunctionId}, pwg::RawAssertionPayload, }; @@ -57,8 +57,15 @@ impl JsExecutionError { None => JsValue::UNDEFINED, }; let assertion_payload = match assertion_payload { - Some(raw) => ::from_serde(&raw) - .expect("Cannot serialize assertion payload"), + Some(raw) => { + let stringified_raw_payload: RawAssertionPayload = RawAssertionPayload { + selector: raw.selector, + data: raw.data.into_iter().map(|x| x.to_hex()).collect(), + }; + + ::from_serde(&stringified_raw_payload) + .expect("Cannot serialize assertion payload") + } None => JsValue::UNDEFINED, }; diff --git a/acvm-repo/acvm_js/test/shared/addition.ts b/acvm-repo/acvm_js/test/shared/addition.ts index 2b8124e77d7..cceb1c1fd61 100644 --- a/acvm-repo/acvm_js/test/shared/addition.ts +++ b/acvm-repo/acvm_js/test/shared/addition.ts @@ -2,11 +2,11 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `addition_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 65, 14, 128, 32, 12, 4, 65, 124, 80, 75, 91, 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, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 149, 143, 49, 10, 128, 48, 12, 69, 127, 170, 7, 113, 212, 77, 241, 8, 34, 56, 137, + 163, 139, 155, 7, 16, 55, 199, 30, 65, 188, 128, 167, 16, 61, 78, 55, 71, 23, 119, 29, 90, 140, 116, 105, 31, 132, 36, + 240, 73, 254, 39, 252, 9, 223, 34, 216, 4, 186, 71, 112, 130, 200, 67, 43, 152, 54, 237, 235, 81, 101, 107, 178, 55, + 229, 38, 101, 219, 197, 249, 89, 77, 199, 48, 23, 234, 94, 46, 237, 195, 241, 46, 132, 121, 192, 102, 179, 3, 95, 38, + 206, 3, 2, 103, 244, 195, 16, 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 24fbc1a921a..762704b80d3 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, 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, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 181, 84, 219, 10, 194, 48, 12, 109, 154, 109, 22, 244, 201, 47, 24, 232, 127, 137, + 12, 223, 42, 250, 232, 231, 187, 66, 50, 178, 88, 181, 233, 182, 64, 73, 27, 206, 201, 101, 39, 12, 220, 220, 194, + 120, 128, 238, 13, 121, 79, 62, 197, 81, 225, 25, 219, 187, 34, 3, 40, 199, 86, 215, 240, 110, 251, 26, 232, 236, 53, + 146, 161, 177, 142, 225, 123, 89, 230, 54, 245, 207, 61, 75, 253, 211, 110, 180, 227, 233, 232, 189, 35, 31, 52, 193, + 187, 207, 165, 153, 117, 66, 254, 64, 126, 120, 220, 159, 241, 246, 186, 12, 215, 24, 247, 50, 169, 226, 24, 6, 192, + 160, 106, 25, 249, 211, 144, 223, 240, 156, 119, 97, 159, 61, 243, 177, 142, 15, 204, 111, 234, 248, 216, 9, 222, 20, + 20, 119, 206, 155, 116, 97, 193, 73, 47, 204, 80, 53, 61, 217, 73, 189, 207, 10, 7, 5, 57, 216, 228, 127, 233, 23, 30, + 50, 248, 127, 156, 181, 164, 172, 92, 185, 246, 152, 9, 114, 174, 55, 111, 172, 240, 81, 180, 5, 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 da0b9974c61..5d8cc95719e 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, 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, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 149, 81, 237, 10, 128, 32, 12, 116, 246, 193, 160, 127, 61, 65, 111, 22, 17, 253, + 8, 164, 31, 17, 61, 127, 69, 91, 204, 156, 48, 7, 58, 61, 239, 240, 142, 129, 139, 11, 239, 5, 116, 174, 169, 131, 75, + 139, 177, 193, 153, 10, 192, 206, 141, 254, 243, 223, 70, 15, 222, 32, 236, 168, 175, 219, 185, 236, 199, 56, 79, 33, + 52, 4, 225, 143, 250, 244, 170, 192, 27, 74, 95, 229, 122, 104, 21, 80, 70, 146, 17, 152, 251, 198, 208, 166, 32, 21, + 185, 123, 14, 239, 21, 156, 157, 92, 163, 94, 232, 115, 22, 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 2f0fbfb85f1..26d9fa1a3d4 100644 --- a/acvm-repo/acvm_js/test/shared/memory_op.ts +++ b/acvm-repo/acvm_js/test/shared/memory_op.ts @@ -1,9 +1,8 @@ // See `memory_op_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 144, 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, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 165, 81, 65, 10, 0, 32, 8, 115, 106, 255, 232, 255, 175, 172, 131, 70, 129, 7, 211, + 129, 108, 135, 13, 28, 3, 189, 24, 251, 196, 180, 51, 27, 227, 210, 76, 49, 38, 165, 128, 110, 14, 159, 57, 201, 123, + 187, 221, 170, 185, 114, 55, 205, 123, 207, 166, 190, 165, 4, 15, 104, 144, 91, 71, 10, 197, 194, 40, 2, 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 fac77e4ee27..42ee70b82d8 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, 10, 0, 48, 8, 114, 107, 231, 255, 255, 59, 86, 204, 64, 22, 136, 102, - 89, 5, 175, 182, 163, 80, 7, 47, 135, 73, 31, 56, 228, 42, 218, 196, 203, 221, 38, 243, 78, 61, 28, 147, 119, 65, 31, - 146, 53, 230, 210, 135, 252, 255, 179, 90, 23, 212, 196, 199, 187, 192, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 141, 11, 10, 0, 32, 12, 66, 87, 235, 127, 255, 3, 183, 224, 5, 214, 64, 84, 68, + 151, 236, 189, 21, 72, 232, 195, 35, 224, 226, 47, 50, 236, 232, 155, 23, 184, 194, 45, 208, 217, 153, 120, 147, 13, + 167, 83, 37, 51, 249, 169, 221, 255, 54, 129, 45, 40, 232, 188, 0, 0, 0, ]); export const initialWitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], @@ -10,6 +10,7 @@ export const initialWitnessMap = new Map([ [3, '0x0000000000000000000000000000000000000000000000000000000000000000'], [4, '0x0000000000000000000000000000000000000000000000000000000000000001'], [5, '0x0000000000000000000000000000000000000000000000000000000000000000'], + [6, '0x0000000000000000000000000000000000000000000000000000000000000001'], ]); export const expectedWitnessMap = new Map([ @@ -19,6 +20,7 @@ export const expectedWitnessMap = new Map([ [4, '0x0000000000000000000000000000000000000000000000000000000000000001'], [5, '0x0000000000000000000000000000000000000000000000000000000000000000'], [6, '0x0000000000000000000000000000000000000000000000000000000000000001'], - [7, '0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c'], - [8, '0x0000000000000000000000000000000000000000000000000000000000000000'], + [7, '0x0000000000000000000000000000000000000000000000000000000000000001'], + [8, '0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c'], + [9, '0x0000000000000000000000000000000000000000000000000000000000000000'], ]); 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 3464809dfc4..560ead8e2c5 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, 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, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 181, 81, 59, 10, 131, 64, 16, 157, 15, 222, 35, 101, 210, 37, 228, 8, 33, 144, 42, + 88, 218, 216, 121, 0, 177, 179, 244, 8, 226, 5, 60, 133, 232, 113, 236, 44, 109, 236, 85, 88, 101, 92, 23, 119, 45, + 124, 240, 96, 216, 125, 204, 188, 55, 195, 176, 5, 43, 206, 240, 38, 226, 68, 18, 255, 168, 8, 203, 187, 77, 196, 218, + 128, 85, 120, 3, 39, 32, 9, 237, 51, 250, 39, 237, 171, 124, 212, 254, 183, 202, 178, 32, 188, 191, 187, 95, 218, 196, + 249, 167, 29, 138, 94, 13, 115, 236, 187, 26, 148, 53, 30, 232, 25, 182, 33, 23, 156, 205, 35, 181, 182, 60, 228, 222, + 151, 60, 165, 39, 225, 107, 119, 8, 253, 74, 122, 205, 96, 118, 108, 90, 204, 149, 193, 209, 189, 175, 53, 147, 9, 35, + 191, 119, 205, 214, 247, 2, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ @@ -53,7 +53,7 @@ export const expectedWitnessStack: WitnessStack = [ ]; export const expectedCompressedWitnessStack = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 237, 145, 177, 13, 0, 32, 8, 4, 17, 117, 31, 75, 75, 87, 113, 255, 37, 44, 196, 5, - 228, 42, 194, 39, 132, 238, 114, 249, 239, 114, 163, 118, 47, 203, 254, 240, 101, 23, 152, 213, 120, 199, 73, 58, 42, - 200, 170, 176, 87, 238, 27, 119, 95, 201, 238, 190, 89, 7, 37, 195, 196, 176, 4, 5, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 237, 144, 49, 10, 0, 32, 12, 3, 99, 85, 16, 95, 225, 255, 95, 233, 160, 142, 66, + 111, 44, 244, 160, 219, 209, 132, 116, 29, 236, 222, 99, 201, 197, 44, 208, 109, 60, 99, 144, 12, 3, 110, 133, 127, + 115, 159, 191, 171, 192, 221, 55, 110, 127, 96, 15, 4, 3, 0, 0, ]); diff --git a/acvm-repo/acvm_js/test/shared/witness_compression.ts b/acvm-repo/acvm_js/test/shared/witness_compression.ts index d2326c1b11b..441be1ba872 100644 --- a/acvm-repo/acvm_js/test/shared/witness_compression.ts +++ b/acvm-repo/acvm_js/test/shared/witness_compression.ts @@ -9,9 +9,8 @@ // after recompiling Noir to print the witness byte array to be written to file after execution export const expectedCompressedWitnessMap = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 173, 206, 185, 13, 0, 48, 8, 67, 209, 144, 107, 30, 146, 44, 144, 253, 167, 162, - 65, 130, 158, 239, 198, 174, 158, 44, 45, 178, 211, 254, 222, 90, 203, 17, 206, 186, 29, 252, 53, 64, 107, 114, 150, - 46, 206, 122, 6, 24, 73, 44, 193, 220, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 149, 204, 185, 17, 0, 0, 8, 2, 65, 240, 171, 195, 254, 171, 52, 212, 16, 47, 34, + 216, 129, 216, 234, 236, 134, 20, 169, 91, 179, 199, 175, 63, 108, 232, 22, 169, 91, 31, 143, 90, 63, 92, 28, 1, 0, 0, ]); export const expectedWitnessMap = new Map([ diff --git a/acvm-repo/blackbox_solver/Cargo.toml b/acvm-repo/blackbox_solver/Cargo.toml index 19331880ee7..67aa01e33bd 100644 --- a/acvm-repo/blackbox_solver/Cargo.toml +++ b/acvm-repo/blackbox_solver/Cargo.toml @@ -19,7 +19,6 @@ workspace = true acir.workspace = true thiserror.workspace = true log.workspace = true -num-bigint = "0.4" blake2 = "0.10.6" blake3 = "1.5.0" diff --git a/acvm-repo/blackbox_solver/src/bigint.rs b/acvm-repo/blackbox_solver/src/bigint.rs deleted file mode 100644 index a4805669726..00000000000 --- a/acvm-repo/blackbox_solver/src/bigint.rs +++ /dev/null @@ -1,241 +0,0 @@ -use std::collections::HashMap; - -use acir::BlackBoxFunc; - -use num_bigint::BigUint; - -use crate::BlackBoxResolutionError; - -/// Resolve BigInt opcodes by storing BigInt values (and their moduli) by their ID in a HashMap: -/// - When it encounters a bigint operation opcode, it performs the operation on the stored values -/// and store the result using the provided ID. -/// - When it gets a to_bytes opcode, it simply looks up the value and resolves the output witness accordingly. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct BigIntSolver { - bigint_id_to_value: HashMap, - bigint_id_to_modulus: HashMap, - - // Use pedantic ACVM solving - pedantic_solving: bool, -} - -impl BigIntSolver { - pub fn with_pedantic_solving(pedantic_solving: bool) -> BigIntSolver { - BigIntSolver { - bigint_id_to_value: Default::default(), - bigint_id_to_modulus: Default::default(), - pedantic_solving, - } - } - - pub fn pedantic_solving(&self) -> bool { - self.pedantic_solving - } - - pub fn get_bigint( - &self, - id: u32, - func: BlackBoxFunc, - ) -> Result { - self.bigint_id_to_value - .get(&id) - .ok_or(BlackBoxResolutionError::Failed( - func, - format!("could not find bigint of id {id}"), - )) - .cloned() - } - - pub fn get_modulus( - &self, - id: u32, - func: BlackBoxFunc, - ) -> Result { - self.bigint_id_to_modulus - .get(&id) - .ok_or(BlackBoxResolutionError::Failed( - func, - format!("could not find bigint of id {id}"), - )) - .cloned() - } - pub fn bigint_from_bytes( - &mut self, - inputs: &[u8], - modulus: &[u8], - output: u32, - ) -> Result<(), BlackBoxResolutionError> { - if self.pedantic_solving { - if !self.is_valid_modulus(modulus) { - panic!("--pedantic-solving: bigint_from_bytes: disallowed modulus {modulus:?}"); - } - if inputs.len() > modulus.len() { - panic!( - "--pedantic-solving: bigint_from_bytes: inputs.len() > modulus.len() {:?}", - (inputs.len(), modulus.len()) - ); - } - } - let bigint = BigUint::from_bytes_le(inputs); - self.bigint_id_to_value.insert(output, bigint); - let modulus = BigUint::from_bytes_le(modulus); - self.bigint_id_to_modulus.insert(output, modulus); - Ok(()) - } - - pub fn bigint_to_bytes(&self, input: u32) -> Result, BlackBoxResolutionError> { - let bigint = self.get_bigint(input, BlackBoxFunc::BigIntToLeBytes)?; - Ok(bigint.to_bytes_le()) - } - - pub fn bigint_op( - &mut self, - lhs: u32, - rhs: u32, - output: u32, - func: BlackBoxFunc, - ) -> Result<(), BlackBoxResolutionError> { - let modulus = self.get_modulus(lhs, func)?; - let lhs = self.get_bigint(lhs, func)?; - let rhs = self.get_bigint(rhs, func)?; - let mut result = match func { - BlackBoxFunc::BigIntAdd => lhs + rhs, - BlackBoxFunc::BigIntSub => { - if lhs >= rhs { - &lhs - &rhs - } else { - &lhs + &modulus - &rhs - } - } - BlackBoxFunc::BigIntMul => lhs * rhs, - BlackBoxFunc::BigIntDiv => { - if self.pedantic_solving && rhs == BigUint::ZERO { - return Err(BlackBoxResolutionError::Failed( - func, - "Attempted to divide BigInt by zero".to_string(), - )); - } - lhs * rhs.modpow(&(&modulus - BigUint::from(2_u32)), &modulus) // cSpell:disable-line - } - _ => unreachable!("ICE - bigint_op must be called for an operation"), - }; - if result > modulus { - let q = &result / &modulus; - result -= q * &modulus; - } - self.bigint_id_to_value.insert(output, result); - self.bigint_id_to_modulus.insert(output, modulus); - Ok(()) - } - - pub fn allowed_bigint_moduli() -> Vec> { - let bn254_fq: Vec = vec![ - 0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x68, 0x91, 0x6a, - 0x81, 0x97, 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, - 0x72, 0x4e, 0x64, 0x30, - ]; - let bn254_fr: Vec = vec![ - 1, 0, 0, 240, 147, 245, 225, 67, 145, 112, 185, 121, 72, 232, 51, 40, 93, 88, 129, 129, - 182, 69, 80, 184, 41, 160, 49, 225, 114, 78, 100, 48, - ]; - let secpk1_fr: Vec = vec![ - 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF, 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, - 0xAE, 0xBA, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - ]; - let secpk1_fq: Vec = vec![ - 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - ]; - let secpr1_fq: Vec = vec![ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, - ]; - let secpr1_fr: Vec = vec![ - 81, 37, 99, 252, 194, 202, 185, 243, 132, 158, 23, 167, 173, 250, 230, 188, 255, 255, - 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, - ]; - vec![bn254_fq, bn254_fr, secpk1_fr, secpk1_fq, secpr1_fq, secpr1_fr] - } - - pub fn is_valid_modulus(&self, modulus: &[u8]) -> bool { - Self::allowed_bigint_moduli().into_iter().any(|allowed_modulus| allowed_modulus == modulus) - } -} - -/// Wrapper over the generic bigint solver to automatically assign bigint IDs. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct BigIntSolverWithId { - solver: BigIntSolver, - last_id: u32, -} - -impl BigIntSolverWithId { - pub fn with_pedantic_solving(pedantic_solving: bool) -> BigIntSolverWithId { - let solver = BigIntSolver::with_pedantic_solving(pedantic_solving); - BigIntSolverWithId { solver, last_id: Default::default() } - } - - pub fn create_bigint_id(&mut self) -> u32 { - let output = self.last_id; - self.last_id += 1; - output - } - - pub fn bigint_from_bytes( - &mut self, - inputs: &[u8], - modulus: &[u8], - ) -> Result { - let id = self.create_bigint_id(); - self.solver.bigint_from_bytes(inputs, modulus, id)?; - Ok(id) - } - - pub fn bigint_to_bytes(&self, input: u32) -> Result, BlackBoxResolutionError> { - self.solver.bigint_to_bytes(input) - } - - pub fn bigint_op( - &mut self, - lhs: u32, - rhs: u32, - func: BlackBoxFunc, - ) -> Result { - let modulus_lhs = self.solver.get_modulus(lhs, func)?; - let modulus_rhs = self.solver.get_modulus(rhs, func)?; - if modulus_lhs != modulus_rhs { - return Err(BlackBoxResolutionError::Failed( - func, - "moduli should be identical in BigInt operation".to_string(), - )); - } - let id = self.create_bigint_id(); - self.solver.bigint_op(lhs, rhs, id, func)?; - Ok(id) - } -} - -#[test] -fn all_allowed_bigint_moduli_are_prime() { - use num_prime::Primality; - use num_prime::nt_funcs::is_prime; // cSpell:disable-line - - for modulus in BigIntSolver::allowed_bigint_moduli() { - let modulus = BigUint::from_bytes_le(&modulus); - let prime_test_config = None; - match is_prime(&modulus, prime_test_config) { - Primality::Yes => (), - Primality::No => panic!("not all allowed_bigint_moduli are prime: {modulus}"), - Primality::Probable(probability) => { - if probability < 0.90 { - panic!( - "not all allowed_bigint_moduli are prime within the allowed probability: {probability} < 0.90" - ); - } - } - } - } -} diff --git a/acvm-repo/blackbox_solver/src/curve_specific_solver.rs b/acvm-repo/blackbox_solver/src/curve_specific_solver.rs index af0104b54f0..eaf31fbfce4 100644 --- a/acvm-repo/blackbox_solver/src/curve_specific_solver.rs +++ b/acvm-repo/blackbox_solver/src/curve_specific_solver.rs @@ -23,11 +23,7 @@ pub trait BlackBoxFunctionSolver { input2_y: &F, input2_infinite: &F, ) -> Result<(F, F, F), BlackBoxResolutionError>; - fn poseidon2_permutation( - &self, - inputs: &[F], - len: u32, - ) -> Result, BlackBoxResolutionError>; + fn poseidon2_permutation(&self, inputs: &[F]) -> Result, BlackBoxResolutionError>; } // pedantic_solving: bool @@ -73,11 +69,7 @@ impl BlackBoxFunctionSolver for StubbedBlackBoxSolver { ) -> Result<(F, F, F), BlackBoxResolutionError> { Err(Self::fail(BlackBoxFunc::EmbeddedCurveAdd)) } - fn poseidon2_permutation( - &self, - _inputs: &[F], - _len: u32, - ) -> Result, BlackBoxResolutionError> { + fn poseidon2_permutation(&self, _inputs: &[F]) -> Result, BlackBoxResolutionError> { Err(Self::fail(BlackBoxFunc::Poseidon2Permutation)) } } diff --git a/acvm-repo/blackbox_solver/src/lib.rs b/acvm-repo/blackbox_solver/src/lib.rs index 97b7977066f..b63e6350a62 100644 --- a/acvm-repo/blackbox_solver/src/lib.rs +++ b/acvm-repo/blackbox_solver/src/lib.rs @@ -9,14 +9,12 @@ use acir::BlackBoxFunc; use thiserror::Error; mod aes128; -mod bigint; mod curve_specific_solver; mod ecdsa; mod hash; mod logic; pub use aes128::aes128_encrypt; -pub use bigint::{BigIntSolver, BigIntSolverWithId}; pub use curve_specific_solver::{BlackBoxFunctionSolver, StubbedBlackBoxSolver}; pub use ecdsa::{ecdsa_secp256k1_verify, ecdsa_secp256r1_verify}; pub use hash::{blake2s, blake3, keccakf1600, sha256_compression}; diff --git a/acvm-repo/bn254_blackbox_solver/benches/criterion.rs b/acvm-repo/bn254_blackbox_solver/benches/criterion.rs index 05211264beb..7b10289d767 100644 --- a/acvm-repo/bn254_blackbox_solver/benches/criterion.rs +++ b/acvm-repo/bn254_blackbox_solver/benches/criterion.rs @@ -9,7 +9,7 @@ use pprof::criterion::{Output, PProfProfiler}; fn bench_poseidon2(c: &mut Criterion) { let inputs = [FieldElement::zero(); 4]; - c.bench_function("poseidon2", |b| b.iter(|| poseidon2_permutation(black_box(&inputs), 4))); + c.bench_function("poseidon2", |b| b.iter(|| poseidon2_permutation(black_box(&inputs)))); } criterion_group!( diff --git a/acvm-repo/bn254_blackbox_solver/src/lib.rs b/acvm-repo/bn254_blackbox_solver/src/lib.rs index 6e80fe77d58..6a06b521422 100644 --- a/acvm-repo/bn254_blackbox_solver/src/lib.rs +++ b/acvm-repo/bn254_blackbox_solver/src/lib.rs @@ -54,8 +54,7 @@ impl BlackBoxFunctionSolver for Bn254BlackBoxSolver { fn poseidon2_permutation( &self, inputs: &[FieldElement], - len: u32, ) -> Result, BlackBoxResolutionError> { - poseidon2_permutation(inputs, len) + poseidon2_permutation(inputs) } } diff --git a/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs b/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs index 1b2bcc612b8..fceb6aa3fb5 100644 --- a/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs +++ b/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs @@ -6,10 +6,9 @@ use crate::FieldElement; pub fn poseidon2_permutation( inputs: &[FieldElement], - len: u32, ) -> Result, BlackBoxResolutionError> { let poseidon = Poseidon2::new(); - poseidon.permutation(inputs, len) + poseidon.permutation(inputs) } pub(crate) struct Poseidon2<'a> { @@ -491,22 +490,11 @@ impl Poseidon2<'_> { pub(crate) fn permutation( &self, inputs: &[FieldElement], - len: u32, ) -> Result, BlackBoxResolutionError> { - if len as usize != inputs.len() { + if inputs.len() != self.config.t as usize { return Err(BlackBoxResolutionError::Failed( acir::BlackBoxFunc::Poseidon2Permutation, - format!( - "the number of inputs does not match specified length. {} > {}", - inputs.len(), - len - ), - )); - } - if len != self.config.t { - return Err(BlackBoxResolutionError::Failed( - acir::BlackBoxFunc::Poseidon2Permutation, - format!("Expected {} values but encountered {}", self.config.t, len), + format!("Expected {} values but encountered {}", self.config.t, inputs.len()), )); } // Read witness assignments @@ -584,7 +572,7 @@ impl<'a> Poseidon2Sponge<'a> { for i in 0..self.rate { self.state[i] += self.cache[i]; } - self.state = self.poseidon.permutation(&self.state, 4)?; + self.state = self.poseidon.permutation(&self.state)?; Ok(()) } @@ -621,7 +609,7 @@ mod test { #[test] fn smoke_test() { let inputs = [FieldElement::zero(); 4]; - let result = poseidon2_permutation(&inputs, 4).expect("should successfully permute"); + let result = poseidon2_permutation(&inputs).expect("should successfully permute"); let expected_result = [ field_from_hex("18DFB8DC9B82229CFF974EFEFC8DF78B1CE96D9D844236B496785C698BC6732E"), diff --git a/acvm-repo/brillig/Cargo.toml b/acvm-repo/brillig/Cargo.toml index aced55447e1..c75384df077 100644 --- a/acvm-repo/brillig/Cargo.toml +++ b/acvm-repo/brillig/Cargo.toml @@ -21,11 +21,7 @@ serde.workspace = true proptest = { workspace = true, optional = true } proptest-derive = { workspace = true, optional = true } -[dev-dependencies] -serde_json.workspace = true -proptest.workspace = true -proptest-derive.workspace = true -num-bigint.workspace = true + [features] default = [] diff --git a/acvm-repo/brillig/README.md b/acvm-repo/brillig/README.md index b74c1b9286c..b3807f50653 100644 --- a/acvm-repo/brillig/README.md +++ b/acvm-repo/brillig/README.md @@ -182,7 +182,7 @@ One possible Brillig output would be: } }, { // location = 6 - "JumpIfNot": { + "JumpIf": { "condition": 4, "location": 9 } diff --git a/acvm-repo/brillig/proptest-regressions/foreign_call.txt b/acvm-repo/brillig/proptest-regressions/foreign_call.txt new file mode 100644 index 00000000000..d6498023627 --- /dev/null +++ b/acvm-repo/brillig/proptest-regressions/foreign_call.txt @@ -0,0 +1,8 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc 30f7fee85ae9843e288940a61dbb5cbeb2ffc179562158edac5e18712c355d7e # shrinks to param = Array([]) +cc 30071c0f928fd334440c27bcc3913f9db59f66380296c29698bd19d0f031a1d3 # shrinks to param = ForeignCallResult { values: [Array([])] } diff --git a/acvm-repo/brillig/src/black_box.rs b/acvm-repo/brillig/src/black_box.rs index 3d9060b2229..5ef722cdcaf 100644 --- a/acvm-repo/brillig/src/black_box.rs +++ b/acvm-repo/brillig/src/black_box.rs @@ -42,21 +42,9 @@ pub enum BlackBoxOp { input2_infinite: MemoryAddress, result: HeapArray, }, - /// BigInt addition - BigIntAdd { lhs: MemoryAddress, rhs: MemoryAddress, output: MemoryAddress }, - /// BigInt subtraction - BigIntSub { lhs: MemoryAddress, rhs: MemoryAddress, output: MemoryAddress }, - /// BigInt multiplication - BigIntMul { lhs: MemoryAddress, rhs: MemoryAddress, output: MemoryAddress }, - /// BigInt division - BigIntDiv { lhs: MemoryAddress, rhs: MemoryAddress, output: MemoryAddress }, - /// BigInt from le bytes - BigIntFromLeBytes { inputs: HeapVector, modulus: HeapVector, output: MemoryAddress }, - /// BigInt to le bytes - BigIntToLeBytes { input: MemoryAddress, output: HeapVector }, /// Applies the Poseidon2 permutation function to the given state, /// outputting the permuted state. - Poseidon2Permutation { message: HeapVector, output: HeapArray, len: MemoryAddress }, + Poseidon2Permutation { message: HeapVector, output: HeapArray }, /// Applies the SHA-256 compression function to the input message Sha256Compression { input: HeapArray, hash_values: HeapArray, output: HeapArray }, /// Returns a decomposition in `num_limbs` limbs of the given input over the given radix. @@ -139,29 +127,8 @@ impl std::fmt::Display for BlackBoxOp { "embedded_curve_add(input1_x: {input1_x}, input1_y: {input1_y}, input1_infinite: {input1_infinite}, input2_x: {input2_x}, input2_y: {input2_y}, input2_infinite: {input2_infinite}, result: {result})" ) } - BlackBoxOp::BigIntAdd { lhs, rhs, output } => { - write!(f, "big_int_add(lhs: {lhs}, rhs: {rhs}, output: {output})") - } - BlackBoxOp::BigIntSub { lhs, rhs, output } => { - write!(f, "big_int_sub(lhs: {lhs}, rhs: {rhs}, output: {output})") - } - BlackBoxOp::BigIntMul { lhs, rhs, output } => { - write!(f, "big_int_mul(lhs: {lhs}, rhs: {rhs}, output: {output})") - } - BlackBoxOp::BigIntDiv { lhs, rhs, output } => { - write!(f, "big_int_div(lhs: {lhs}, rhs: {rhs}, output: {output})") - } - BlackBoxOp::BigIntFromLeBytes { inputs, modulus, output } => { - write!( - f, - "big_int_from_le_bytes(inputs: {inputs}, modulus: {modulus}, output: {output})" - ) - } - BlackBoxOp::BigIntToLeBytes { input, output } => { - write!(f, "big_int_to_le_bytes(input: {input}, output: {output})") - } - BlackBoxOp::Poseidon2Permutation { message, output, len } => { - write!(f, "poseidon2_permutation(message: {message}, len: {len}, output: {output})") + BlackBoxOp::Poseidon2Permutation { message, output } => { + write!(f, "poseidon2_permutation(message: {message}, output: {output})") } BlackBoxOp::Sha256Compression { input, hash_values, output } => { write!( diff --git a/acvm-repo/brillig/src/foreign_call.rs b/acvm-repo/brillig/src/foreign_call.rs index 0f56902281d..1036a262255 100644 --- a/acvm-repo/brillig/src/foreign_call.rs +++ b/acvm-repo/brillig/src/foreign_call.rs @@ -3,7 +3,6 @@ use serde::{Deserialize, Serialize}; /// Single input or output of a [foreign call][crate::Opcode::ForeignCall]. #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)] -#[cfg_attr(test, derive(proptest_derive::Arbitrary))] #[serde(untagged)] pub enum ForeignCallParam { Single(F), @@ -41,7 +40,6 @@ impl ForeignCallParam { /// Represents the full output of a [foreign call][crate::Opcode::ForeignCall]. #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone, Default)] -#[cfg_attr(test, derive(proptest_derive::Arbitrary))] pub struct ForeignCallResult { /// Resolved output values of the foreign call. pub values: Vec>, @@ -64,43 +62,3 @@ impl From>> for ForeignCallResult { ForeignCallResult { values } } } - -#[cfg(test)] -mod test { - use acir_field::FieldElement; - use proptest::prelude::*; - - use super::{ForeignCallParam, ForeignCallResult}; - - // Define a wrapper around field so we can implement `Arbitrary`. - // NB there are other methods like `arbitrary_field_elements` around the codebase, - // but for `proptest_derive::Arbitrary` we need `F: AcirField + Arbitrary`. - acir_field::field_wrapper!(TestField, FieldElement); - - impl Arbitrary for TestField { - type Parameters = (); - type Strategy = BoxedStrategy; - - fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { - any::().prop_map(|v| Self(FieldElement::from(v))).boxed() - } - } - - proptest! { - #[test] - fn foreign_call_arg_serialization_roundtrip(param: ForeignCallParam) { - let serialized = serde_json::to_string(¶m).unwrap(); - let deserialized: ForeignCallParam = serde_json::from_str(&serialized).unwrap(); - - prop_assert_eq!(param, deserialized); - } - - #[test] - fn foreign_call_return_serialization_roundtrip(param: ForeignCallResult) { - let serialized = serde_json::to_string(¶m).unwrap(); - let deserialized: ForeignCallResult = serde_json::from_str(&serialized).unwrap(); - - prop_assert_eq!(param, deserialized); - } - } -} diff --git a/acvm-repo/brillig/src/opcodes.rs b/acvm-repo/brillig/src/opcodes.rs index 292328c764b..f56d7cfdb07 100644 --- a/acvm-repo/brillig/src/opcodes.rs +++ b/acvm-repo/brillig/src/opcodes.rs @@ -345,12 +345,6 @@ pub enum BrilligOpcode { source: MemoryAddress, bit_size: BitSize, }, - /// Sets the program counter to the value of `location` if - /// the value at the `condition` address is zero. - JumpIfNot { - condition: MemoryAddress, - location: Label, - }, /// Sets the program counter to the value of `location` /// If the value at `condition` is non-zero JumpIf { @@ -461,9 +455,6 @@ impl std::fmt::Display for BrilligOpcode { BrilligOpcode::Cast { destination, source, bit_size } => { write!(f, "{destination} = cast {source} to {bit_size}") } - BrilligOpcode::JumpIfNot { condition, location } => { - write!(f, "jump if not {condition} to {location}") - } BrilligOpcode::JumpIf { condition, location } => { write!(f, "jump if {condition} to {location}") } diff --git a/acvm-repo/brillig_vm/src/black_box.rs b/acvm-repo/brillig_vm/src/black_box.rs index e5e9c07b31b..7f239f92c5f 100644 --- a/acvm-repo/brillig_vm/src/black_box.rs +++ b/acvm-repo/brillig_vm/src/black_box.rs @@ -2,8 +2,8 @@ use acir::brillig::{BlackBoxOp, HeapArray, HeapVector}; use acir::{AcirField, BlackBoxFunc}; use acvm_blackbox_solver::{ - BigIntSolverWithId, BlackBoxFunctionSolver, BlackBoxResolutionError, aes128_encrypt, blake2s, - blake3, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, keccakf1600, sha256_compression, + BlackBoxFunctionSolver, BlackBoxResolutionError, aes128_encrypt, blake2s, blake3, + ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, keccakf1600, sha256_compression, }; use num_bigint::BigUint; use num_traits::Zero; @@ -43,8 +43,6 @@ fn to_value_vec(input: &[u8]) -> Vec> { input.iter().map(|&x| x.into()).collect() } -pub(crate) type BrilligBigIntSolver = BigIntSolverWithId; - /// Evaluates a black box function inside the VM, performing the actual native computation. /// /// Delegates the execution to the corresponding cryptographic or arithmetic @@ -68,7 +66,6 @@ pub(crate) fn evaluate_black_box op: &BlackBoxOp, solver: &Solver, memory: &mut Memory, - bigint_solver: &mut BrilligBigIntSolver, ) -> Result<(), BlackBoxResolutionError> { match op { BlackBoxOp::AES128Encrypt { inputs, iv, key, outputs } => { @@ -235,68 +232,10 @@ pub(crate) fn evaluate_black_box ); Ok(()) } - BlackBoxOp::BigIntAdd { lhs, rhs, output } => { - let lhs = memory.read(*lhs).expect_u32().unwrap(); - let rhs = memory.read(*rhs).expect_u32().unwrap(); - - let new_id = bigint_solver.bigint_op(lhs, rhs, BlackBoxFunc::BigIntAdd)?; - memory.write(*output, new_id.into()); - Ok(()) - } - BlackBoxOp::BigIntSub { lhs, rhs, output } => { - let lhs = memory.read(*lhs).expect_u32().unwrap(); - let rhs = memory.read(*rhs).expect_u32().unwrap(); - - let new_id = bigint_solver.bigint_op(lhs, rhs, BlackBoxFunc::BigIntSub)?; - memory.write(*output, new_id.into()); - Ok(()) - } - BlackBoxOp::BigIntMul { lhs, rhs, output } => { - let lhs = memory.read(*lhs).expect_u32().unwrap(); - let rhs = memory.read(*rhs).expect_u32().unwrap(); - - let new_id = bigint_solver.bigint_op(lhs, rhs, BlackBoxFunc::BigIntMul)?; - memory.write(*output, new_id.into()); - Ok(()) - } - BlackBoxOp::BigIntDiv { lhs, rhs, output } => { - let lhs = memory.read(*lhs).expect_u32().unwrap(); - let rhs = memory.read(*rhs).expect_u32().unwrap(); - - let new_id = bigint_solver.bigint_op(lhs, rhs, BlackBoxFunc::BigIntDiv)?; - memory.write(*output, new_id.into()); - Ok(()) - } - BlackBoxOp::BigIntFromLeBytes { inputs, modulus, output } => { - let input = read_heap_vector(memory, inputs); - let input: Vec = input.iter().map(|x| x.expect_u8().unwrap()).collect(); - let modulus = read_heap_vector(memory, modulus); - let modulus: Vec = modulus.iter().map(|x| x.expect_u8().unwrap()).collect(); - - let new_id = bigint_solver.bigint_from_bytes(&input, &modulus)?; - memory.write(*output, new_id.into()); - - Ok(()) - } - BlackBoxOp::BigIntToLeBytes { input, output } => { - let input: u32 = memory.read(*input).expect_u32().unwrap(); - let bytes = bigint_solver.bigint_to_bytes(input)?; - let mut values = Vec::new(); - for i in 0..32 { - if i < bytes.len() { - values.push(bytes[i].into()); - } else { - values.push(0_u8.into()); - } - } - memory.write_slice(memory.read_ref(output.pointer), &values); - Ok(()) - } - BlackBoxOp::Poseidon2Permutation { message, output, len } => { + BlackBoxOp::Poseidon2Permutation { message, output } => { let input = read_heap_vector(memory, message); let input: Vec = input.iter().map(|x| x.expect_field().unwrap()).collect(); - let len = memory.read(*len).expect_u32().unwrap(); - let result = solver.poseidon2_permutation(&input, len)?; + let result = solver.poseidon2_permutation(&input)?; let mut values = Vec::new(); for i in result { values.push(MemoryValue::new_field(i)); @@ -368,12 +307,6 @@ fn black_box_function_from_op(op: &BlackBoxOp) -> BlackBoxFunc { BlackBoxOp::EcdsaSecp256r1 { .. } => BlackBoxFunc::EcdsaSecp256r1, BlackBoxOp::MultiScalarMul { .. } => BlackBoxFunc::MultiScalarMul, BlackBoxOp::EmbeddedCurveAdd { .. } => BlackBoxFunc::EmbeddedCurveAdd, - BlackBoxOp::BigIntAdd { .. } => BlackBoxFunc::BigIntAdd, - BlackBoxOp::BigIntSub { .. } => BlackBoxFunc::BigIntSub, - BlackBoxOp::BigIntMul { .. } => BlackBoxFunc::BigIntMul, - BlackBoxOp::BigIntDiv { .. } => BlackBoxFunc::BigIntDiv, - BlackBoxOp::BigIntFromLeBytes { .. } => BlackBoxFunc::BigIntFromLeBytes, - BlackBoxOp::BigIntToLeBytes { .. } => BlackBoxFunc::BigIntToLeBytes, BlackBoxOp::Poseidon2Permutation { .. } => BlackBoxFunc::Poseidon2Permutation, BlackBoxOp::Sha256Compression { .. } => BlackBoxFunc::Sha256Compression, BlackBoxOp::ToRadix { .. } => unreachable!("ToRadix is not an ACIR BlackBoxFunc"), diff --git a/acvm-repo/brillig_vm/src/lib.rs b/acvm-repo/brillig_vm/src/lib.rs index 322e8ddf902..fa0dcb56187 100644 --- a/acvm-repo/brillig_vm/src/lib.rs +++ b/acvm-repo/brillig_vm/src/lib.rs @@ -17,7 +17,7 @@ use acir::brillig::{ }; use acvm_blackbox_solver::BlackBoxFunctionSolver; use arithmetic::{BrilligArithmeticError, evaluate_binary_field_op, evaluate_binary_int_op}; -use black_box::{BrilligBigIntSolver, evaluate_black_box}; +use black_box::evaluate_black_box; // Re-export `brillig`. pub use acir::brillig; @@ -144,8 +144,6 @@ pub struct VM<'a, F, B: BlackBoxFunctionSolver> { call_stack: Vec, /// The solver for blackbox functions black_box_solver: &'a B, - // The solver for big integers, it is used by the blackbox solver - bigint_solver: BrilligBigIntSolver, // Flag that determines whether we want to profile VM. profiling_active: bool, // Samples for profiling the VM execution. @@ -176,8 +174,6 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { } None => (false, Vec::new(), HashMap::new()), }; - let bigint_solver = - BrilligBigIntSolver::with_pedantic_solving(black_box_solver.pedantic_solving()); Self { calldata, program_counter: 0, @@ -188,7 +184,6 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { memory: Memory::default(), call_stack: Vec::new(), black_box_solver, - bigint_solver, profiling_active, profiling_samples: Vec::with_capacity(bytecode.len()), fuzzing_active, @@ -481,15 +476,6 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { self.fuzzing_trace_branching(self.program_counter + 1); self.increment_program_counter() } - Opcode::JumpIfNot { condition, location: destination } => { - let condition_value = self.memory.read(*condition); - if condition_value.expect_u1().expect("condition value is not a boolean") { - self.fuzzing_trace_branching(self.program_counter + 1); - return self.increment_program_counter(); - } - self.fuzzing_trace_branching(*destination); - self.set_program_counter(*destination) - } Opcode::CalldataCopy { destination_address, size_address, offset_address } => { let size = self.memory.read(*size_address).to_usize(); let offset = self.memory.read(*offset_address).to_usize(); @@ -659,12 +645,7 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { self.increment_program_counter() } Opcode::BlackBox(black_box_op) => { - match evaluate_black_box( - black_box_op, - self.black_box_solver, - &mut self.memory, - &mut self.bigint_solver, - ) { + match evaluate_black_box(black_box_op, self.black_box_solver, &mut self.memory) { Ok(()) => self.increment_program_counter(), Err(e) => self.fail(e.to_string()), } @@ -1264,91 +1245,6 @@ mod tests { assert_eq!(status, VMStatus::Finished { return_data_offset: 0, return_data_size: 0 }); } - #[test] - // cSpell:disable-next-line - fn jmpifnot_opcode() { - let calldata: Vec = vec![1u128.into(), 2u128.into()]; - - let opcodes = vec![ - Opcode::Const { - destination: MemoryAddress::direct(0), - bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(2u64), - }, - Opcode::Const { - destination: MemoryAddress::direct(1), - 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), - }, - Opcode::Jump { location: 6 }, - Opcode::Const { - destination: MemoryAddress::direct(0), - bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(0u64), - }, - Opcode::Trap { - revert_data: HeapVector { - pointer: MemoryAddress::direct(0), - size: MemoryAddress::direct(0), - }, - }, - Opcode::BinaryFieldOp { - op: BinaryFieldOp::Equals, - lhs: MemoryAddress::direct(0), - rhs: MemoryAddress::direct(1), - destination: MemoryAddress::direct(2), - }, - Opcode::JumpIfNot { condition: MemoryAddress::direct(2), location: 4 }, - Opcode::BinaryFieldOp { - op: BinaryFieldOp::Add, - lhs: MemoryAddress::direct(0), - rhs: MemoryAddress::direct(1), - destination: MemoryAddress::direct(2), - }, - ]; - - let solver = StubbedBlackBoxSolver::default(); - let mut vm = VM::new(calldata, &opcodes, &solver, false, None); - - let status = vm.process_opcode(); - assert_eq!(status, VMStatus::InProgress); - let status = vm.process_opcode(); - assert_eq!(status, VMStatus::InProgress); - let status = vm.process_opcode(); - assert_eq!(status, VMStatus::InProgress); - let status = vm.process_opcode(); - assert_eq!(status, VMStatus::InProgress); - let status = vm.process_opcode(); - assert_eq!(status, VMStatus::InProgress); - let status = vm.process_opcode(); - assert_eq!(status, VMStatus::InProgress); - - let output_cmp_value = vm.memory.read(MemoryAddress::direct(2)); - assert_eq!(output_cmp_value.to_field(), false.into()); - - let status = vm.process_opcode(); - assert_eq!(status, VMStatus::InProgress); - - let status = vm.process_opcode(); - assert_eq!( - status, - VMStatus::Failure { - reason: FailureReason::Trap { revert_data_offset: 0, revert_data_size: 0 }, - call_stack: vec![5] - } - ); - - // The address at index `2` should have not changed as we jumped over the add opcode - let VM { memory, .. } = vm; - let output_value = memory.read(MemoryAddress::direct(2)); - assert_eq!(output_value.to_field(), false.into()); - } - #[test] fn cast_opcode() { let calldata: Vec = vec![((2_u128.pow(32)) - 1).into()]; diff --git a/compiler/integration-tests/circuits/recursion/Nargo.toml b/compiler/integration-tests/circuits/recursion/Nargo.toml index f057b6e0021..1900e74b82e 100644 --- a/compiler/integration-tests/circuits/recursion/Nargo.toml +++ b/compiler/integration-tests/circuits/recursion/Nargo.toml @@ -4,3 +4,4 @@ type = "bin" authors = [""] [dependencies] +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages", tag ="v3.0.0-nightly.20250916", directory = "./barretenberg/noir/bb_proof_verification" } diff --git a/compiler/integration-tests/circuits/recursion/src/main.nr b/compiler/integration-tests/circuits/recursion/src/main.nr index a2f8e3b39a5..51d7bbffc9d 100644 --- a/compiler/integration-tests/circuits/recursion/src/main.nr +++ b/compiler/integration-tests/circuits/recursion/src/main.nr @@ -1,16 +1,10 @@ -global HONK_PROOF_SIZE: u32 = 456; -global HONK_IDENTIFIER: u32 = 1; +use bb_proof_verification::{UltraHonkVerificationKey, UltraHonkZKProof, verify_ultrahonkzk_proof}; fn main( - verification_key: [Field; 112], - proof: [Field; HONK_PROOF_SIZE], - public_inputs: [Field; 2] + verification_key: UltraHonkVerificationKey, + proof: UltraHonkZKProof, + public_inputs: [Field; 2], + key_hash: Field, ) { - std::verify_proof_with_type( - verification_key, - proof, - public_inputs, - 0x0, - HONK_IDENTIFIER, - ); + verify_ultrahonkzk_proof(verification_key, proof, public_inputs, key_hash); } diff --git a/compiler/integration-tests/package.json b/compiler/integration-tests/package.json index a6dac29a114..7f803bcd475 100644 --- a/compiler/integration-tests/package.json +++ b/compiler/integration-tests/package.json @@ -8,12 +8,13 @@ "test": "yarn test:browser && yarn test:node", "test:node": "bash ./scripts/setup.sh && hardhat test test/node/prove_and_verify.test.ts && hardhat test test/node/smart_contract_verifier.test.ts && hardhat test test/node/onchain_recursive_verification.test.ts", "test:browser": "web-test-runner", - "test:integration:browser": "web-test-runner test/browser/**/*.test.ts", - "test:integration:browser:watch": "web-test-runner test/browser/**/*.test.ts --watch", + "test:integration:browser": "web-test-runner test/browser/**/*.test.ts --concurrent-browsers 1 --concurrency 1", + "test:browser:a_1_mul": "web-test-runner test/browser/compile_prove_verify.test.ts --concurrent-browsers 1 --concurrency 1", + "test:integration:browser:watch": "web-test-runner test/browser/**/*.test.ts --concurrent-browsers 1 --concurrency 1 --watch", "lint": "NODE_NO_WARNINGS=1 eslint . --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "1.2.0", + "@aztec/bb.js": "v3.0.0-nightly.20250916", "@noir-lang/noir_js": "workspace:*", "@noir-lang/noir_wasm": "workspace:*", "@nomicfoundation/hardhat-chai-matchers": "^2.0.8", diff --git a/compiler/integration-tests/test/browser/compile_prove_verify.test.ts b/compiler/integration-tests/test/browser/compile_prove_verify.test.ts index 61f076effb8..5e3da5744e1 100644 --- a/compiler/integration-tests/test/browser/compile_prove_verify.test.ts +++ b/compiler/integration-tests/test/browser/compile_prove_verify.test.ts @@ -6,28 +6,13 @@ import { TEST_LOG_LEVEL } from '../environment.js'; import { compile, createFileManager } from '@noir-lang/noir_wasm'; import { Noir } from '@noir-lang/noir_js'; import { InputMap } from '@noir-lang/noirc_abi'; -import { UltraHonkBackend } from '@aztec/bb.js'; +import { UltraHonkBackend, UltraHonkVerifierBackend } from '@aztec/bb.js'; import { getFile } from './utils.js'; const logger = new Logger({ name: 'test', minLevel: TEST_LOG_LEVEL }); const debugLogger = logger.debug.bind(logger); -const test_cases = [ - { - case: 'test_programs/execution_success/a_1_mul', - numPublicInputs: 0, - }, - { - case: 'test_programs/execution_success/assert_statement', - numPublicInputs: 1, - }, -]; - -const suite = Mocha.Suite.create(mocha.suite, 'Noir end to end test'); - -suite.timeout(60 * 20e3); //20mins - async function getCircuit(projectPath: string) { const fm = createFileManager('/'); await fm.writeFile('./src/main.nr', await getFile(`${projectPath}/src/main.nr`)); @@ -40,38 +25,55 @@ async function getCircuit(projectPath: string) { return result.program; } -test_cases.forEach((testInfo) => { - const test_name = testInfo.case.split('/').pop(); - const mochaTest = new Mocha.Test(`${test_name} (Compile, Execute, Prove, Verify)`, async () => { - const base_relative_path = '../../../../..'; - const test_case = testInfo.case; +describe('Noir end to end test', function () { + this.timeout(60 * 20e3); // 20 minutes - let noir_program; - try { - noir_program = await getCircuit(`${base_relative_path}/${test_case}`); + it('a_1_mul (Compile, Execute, Prove, Verify)', async () => { + const base_relative_path = '../../../../..'; + const test_case = 'test_programs/execution_success/a_1_mul'; - expect(noir_program, 'Compile output ').to.be.an('object'); - } catch (e) { - expect(e, 'Compilation Step').to.not.be.an('error'); - throw e; - } + const noir_program = await getCircuit(`${base_relative_path}/${test_case}`); + expect(noir_program).to.be.an('object'); const prover_toml = await new Response(await getFile(`${base_relative_path}/${test_case}/Prover.toml`)).text(); const inputs: InputMap = TOML.parse(prover_toml) as InputMap; - // JS Proving - const program = new Noir(noir_program); const { witness } = await program.execute(inputs); const backend = new UltraHonkBackend(noir_program.bytecode, { logger: debugLogger }); const proof = await backend.generateProof(witness); + await backend.destroy(); - // JS verification + const vkBackend = new UltraHonkBackend(noir_program.bytecode, { logger: debugLogger }); + const verificationKey = await vkBackend.getVerificationKey(); + await vkBackend.destroy(); - const verified = await backend.verifyProof(proof); - expect(verified, 'Proof fails verification in JS').to.be.true; + const verifier_backend = new UltraHonkVerifierBackend(); + const verified = await verifier_backend.verifyProof({ ...proof, verificationKey }); + expect(verified).to.be.true; }); - suite.addTest(mochaTest); + it('assert_statement (Compile, Execute, Prove, Verify)', async () => { + const base_relative_path = '../../../../..'; + const test_case = 'test_programs/execution_success/assert_statement'; + + const noir_program = await getCircuit(`${base_relative_path}/${test_case}`); + expect(noir_program).to.be.an('object'); + + const prover_toml = await new Response(await getFile(`${base_relative_path}/${test_case}/Prover.toml`)).text(); + const inputs: InputMap = TOML.parse(prover_toml) as InputMap; + + const program = new Noir(noir_program); + const { witness } = await program.execute(inputs); + + const backend = new UltraHonkBackend(noir_program.bytecode, { logger: debugLogger }); + const proof = await backend.generateProof(witness); + const verificationKey = await backend.getVerificationKey(); + await backend.destroy(); + + const verifier_backend = new UltraHonkVerifierBackend(); + const verified = await verifier_backend.verifyProof({ ...proof, verificationKey }); + expect(verified).to.be.true; + }); }); diff --git a/compiler/integration-tests/test/browser/recursion.test.ts b/compiler/integration-tests/test/browser/recursion.test.ts index e340bd195cb..f6ce526acf8 100644 --- a/compiler/integration-tests/test/browser/recursion.test.ts +++ b/compiler/integration-tests/test/browser/recursion.test.ts @@ -3,7 +3,7 @@ import { TEST_LOG_LEVEL } from '../environment.js'; import { Logger } from 'tslog'; import { acvm, abi, Noir } from '@noir-lang/noir_js'; -import { Barretenberg, deflattenFields, RawBuffer, UltraHonkBackend } from '@aztec/bb.js'; +import { Barretenberg, deflattenFields, RawBuffer, UltraHonkBackend, UltraHonkVerifierBackend } from '@aztec/bb.js'; import { getFile } from './utils.js'; import { InputMap } from '@noir-lang/noirc_abi'; import { createFileManager, compile } from '@noir-lang/noir_wasm'; @@ -49,8 +49,11 @@ describe('It compiles noir program code, receiving circuit bytes and abi object. // Get verification key for inner circuit as fields const innerCircuitVerificationKey = await main_backend.getVerificationKey(); + main_backend.destroy(); + const barretenbergAPI = await Barretenberg.new({ threads: 1 }); const vkAsFields = await barretenbergAPI.acirVkAsFieldsUltraHonk(new RawBuffer(innerCircuitVerificationKey)); + barretenbergAPI.destroy(); const recursion_inputs: InputMap = { verification_key: vkAsFields.map((field) => field.toString()), @@ -69,9 +72,12 @@ describe('It compiles noir program code, receiving circuit bytes and abi object. const { witness: recursion_witnessUint8Array } = await new Noir(recursion_program).execute(recursion_inputs); + logger.debug('About to generate proof...'); const recursion_proof = await recursion_backend.generateProof(recursion_witnessUint8Array); + const verificationKey = await recursion_backend.getVerificationKey(); - const recursion_verification = await recursion_backend.verifyProof(recursion_proof); + const verifierBackend = new UltraHonkVerifierBackend({ logger: debugLogger }, { recursive: false }); + const recursion_verification = await verifierBackend.verifyProof({ ...recursion_proof, verificationKey }); logger.debug('recursion_verification', recursion_verification); diff --git a/compiler/integration-tests/test/mocks/buffer.js b/compiler/integration-tests/test/mocks/buffer.js index 38f35b2f3e3..a7fdc4fb2ee 100644 --- a/compiler/integration-tests/test/mocks/buffer.js +++ b/compiler/integration-tests/test/mocks/buffer.js @@ -1,7 +1,11 @@ import * as buffer from 'buffer-esm'; - const Buffer = buffer.BufferShim; +// bb.js requires `allocUnsafeSlow` which is not present in buffer-esm +if (!Buffer.allocUnsafeSlow) { + Buffer.allocUnsafeSlow = Buffer.allocUnsafe; +} + // bb.js requires writeBigUInt64BE and readBigUInt64BE which are not present in buffer-esm // so we are adding custom implementations 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 90caabaae2d..3015b04ec15 100644 --- a/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts +++ b/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts @@ -24,6 +24,7 @@ it(`smart contract can verify a recursive proof`, async () => { const innerCircuitVerificationKey = await innerBackend.getVerificationKey(); const barretenbergAPI = await Barretenberg.new({ threads: 1 }); const vkAsFields = await barretenbergAPI.acirVkAsFieldsUltraHonk(new RawBuffer(innerCircuitVerificationKey)); + const vkHash = await barretenbergAPI.poseidon2Hash(vkAsFields); // Generate proof of the recursive circuit const recursiveCircuitNoir = new Noir(recursionCircuit as CompiledCircuit); @@ -33,6 +34,7 @@ it(`smart contract can verify a recursive proof`, async () => { proof: deflattenFields(intermediateProof), public_inputs: intermediatePublicInputs, verification_key: vkAsFields.map((field) => field.toString()), + key_hash: vkHash.toString(), }; const { witness: recursiveWitness } = await recursiveCircuitNoir.execute(recursiveInputs); const { proof: recursiveProof, publicInputs: recursivePublicInputs } = await recursiveBackend.generateProof( @@ -49,7 +51,16 @@ it(`smart contract can verify a recursive proof`, async () => { expect(verified).to.be.true; // Smart contract verification - const contract = await ethers.deployContract('contracts/recursion.sol:HonkVerifier', []); + + // Link the ZKTranscriptLib + const ZKTranscriptLib = await ethers.deployContract('contracts/recursion.sol:ZKTranscriptLib'); + await ZKTranscriptLib.waitForDeployment(); + + const contract = await ethers.deployContract('contracts/recursion.sol:HonkVerifier', [], { + libraries: { + ZKTranscriptLib: await ZKTranscriptLib.getAddress(), + }, + }); const result = await contract.verify.staticCall(recursiveProof, recursivePublicInputs); expect(result).to.be.true; diff --git a/compiler/integration-tests/test/node/prove_and_verify.test.ts b/compiler/integration-tests/test/node/prove_and_verify.test.ts index 82b308148c0..36b74dd92c1 100644 --- a/compiler/integration-tests/test/node/prove_and_verify.test.ts +++ b/compiler/integration-tests/test/node/prove_and_verify.test.ts @@ -2,7 +2,7 @@ import { expect } from 'chai'; import assert_lt_json from '../../circuits/assert_lt/target/assert_lt.json' assert { type: 'json' }; import fold_fibonacci_json from '../../circuits/fold_fibonacci/target/fold_fibonacci.json' assert { type: 'json' }; import { Noir } from '@noir-lang/noir_js'; -import { BarretenbergVerifier, UltraHonkBackend } from '@aztec/bb.js'; +import { UltraHonkVerifierBackend, UltraHonkBackend } from '@aztec/bb.js'; import { CompiledCircuit } from '@noir-lang/types'; const assert_lt_program = assert_lt_json as CompiledCircuit; @@ -48,8 +48,8 @@ it('end-to-end proof creation and verification -- Verifier API', async () => { const verificationKey = await honkBackend.getVerificationKey(); // Proof verification - const verifier = new BarretenbergVerifier(); - const isValid = await verifier.verifyUltraHonkProof(proof, verificationKey); + const verifier = new UltraHonkVerifierBackend(); + const isValid = await verifier.verifyProof({ ...proof, verificationKey }); expect(isValid).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 83ce430198d..beb72d87870 100644 --- a/compiler/integration-tests/test/node/smart_contract_verifier.test.ts +++ b/compiler/integration-tests/test/node/smart_contract_verifier.test.ts @@ -14,11 +14,13 @@ const test_cases = [ { case: 'test_programs/execution_success/a_1_mul', compiled: 'contracts/a_1_mul.sol:HonkVerifier', + zk_lib: 'contracts/a_1_mul.sol:ZKTranscriptLib', numPublicInputs: 0, }, { case: 'test_programs/execution_success/assert_statement', compiled: 'contracts/assert_statement.sol:HonkVerifier', + zk_lib: 'contracts/assert_statement.sol:ZKTranscriptLib', numPublicInputs: 1, }, ]; @@ -45,7 +47,7 @@ test_cases.forEach((testInfo) => { const prover_toml = readFileSync(resolve(`${base_relative_path}/${test_case}/Prover.toml`)).toString(); const inputs = toml.parse(prover_toml); const { witness } = await program.execute(inputs); - + console.log(witness); const backend = new UltraHonkBackend(noir_program.bytecode); const proofData = await backend.generateProof(witness, { keccakZK: true }); @@ -56,7 +58,15 @@ test_cases.forEach((testInfo) => { // Smart contract verification - const contract = await ethers.deployContract(testInfo.compiled, []); + // Link the ZKTranscriptLib + const ZKTranscriptLib = await ethers.deployContract(testInfo.zk_lib); + await ZKTranscriptLib.waitForDeployment(); + + const contract = await ethers.deployContract(testInfo.compiled, [], { + libraries: { + ZKTranscriptLib: await ZKTranscriptLib.getAddress(), + }, + }); const result = await contract.verify(proofData.proof, proofData.publicInputs); diff --git a/compiler/integration-tests/web-test-runner.config.mjs b/compiler/integration-tests/web-test-runner.config.mjs index 8cf20bced47..ea9d1c347ca 100644 --- a/compiler/integration-tests/web-test-runner.config.mjs +++ b/compiler/integration-tests/web-test-runner.config.mjs @@ -14,7 +14,7 @@ if (process.env.CI !== 'true' || process.env.RUNNER_DEBUG === '1') { name: 'environment', serve(context) { if (context.path === '/compiler/integration-tests/test/environment.js') { - return 'export const TEST_LOG_LEVEL = 2;'; + return `export const TEST_LOG_LEVEL = 2;`; } }, }); @@ -22,10 +22,14 @@ if (process.env.CI !== 'true' || process.env.RUNNER_DEBUG === '1') { export default { browsers: [ - playwrightLauncher({ product: 'chromium' }), + playwrightLauncher({ + product: 'chromium', + }), // playwrightLauncher({ product: "webkit" }), // playwrightLauncher({ product: "firefox" }), ], + concurrency: 1, + concurrentBrowsers: 1, middleware: [ async (ctx, next) => { if (ctx.url.endsWith('.wasm.gz')) { @@ -36,6 +40,9 @@ export default { if (ctx.url.includes('pino/browser.js')) { ctx.url = '/compiler/integration-tests/test/mocks/pino.js'; } + if (ctx.url.includes('buffer/index.js')) { + ctx.url = '/compiler/integration-tests/test/mocks/buffer.js'; + } await next(); }, ], @@ -44,6 +51,10 @@ export default { ` + diff --git a/compiler/noirc_driver/src/contract.rs b/compiler/noirc_driver/src/contract.rs index b4c5e9a3fca..2357947ebf1 100644 --- a/compiler/noirc_driver/src/contract.rs +++ b/compiler/noirc_driver/src/contract.rs @@ -1,7 +1,10 @@ use serde::{Deserialize, Serialize}; use std::collections::{BTreeMap, HashMap}; -use acvm::{FieldElement, acir::circuit::Program}; +use acvm::{ + FieldElement, + acir::circuit::{ExpressionWidth, Program}, +}; use fm::FileId; use noirc_abi::{Abi, AbiType, AbiValue}; use noirc_errors::debug_info::DebugInfo; @@ -56,10 +59,6 @@ pub struct ContractFunction { pub bytecode: Program, pub debug: Vec, - - /// Names of the functions in the program. These are used for more informative debugging and benchmarking. - pub names: Vec, - - /// Names of the unconstrained functions in the program. - pub brillig_names: Vec, + /// Maximum width of the expressions which will be constrained + pub expression_width: ExpressionWidth, } diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index c30199ce58d..559529badb5 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -685,8 +685,7 @@ fn compile_contract_inner( bytecode: function.program, debug: function.debug, is_unconstrained: modifiers.is_unconstrained, - names: function.names, - brillig_names: function.brillig_names, + expression_width: options.expression_width.unwrap_or(DEFAULT_EXPRESSION_WIDTH), }); } @@ -819,20 +818,15 @@ pub fn compile_no_check( let return_visibility = program.return_visibility(); let ssa_evaluator_options = options.as_ssa_options(context.package_build_path.clone()); - let SsaProgramArtifact { program, debug, warnings, names, brillig_names, error_types, .. } = - if options.minimal_ssa { - create_program_with_minimal_passes( - program, - &ssa_evaluator_options, - &context.file_manager, - )? - } else { - create_program( - program, - &ssa_evaluator_options, - if options.with_ssa_locations { Some(&context.file_manager) } else { None }, - )? - }; + let SsaProgramArtifact { program, debug, warnings, error_types, .. } = if options.minimal_ssa { + create_program_with_minimal_passes(program, &ssa_evaluator_options, &context.file_manager)? + } else { + create_program( + program, + &ssa_evaluator_options, + if options.with_ssa_locations { Some(&context.file_manager) } else { None }, + )? + }; let abi = gen_abi(context, &main_function, return_visibility, error_types); let file_map = filter_relevant_files(&debug, &context.file_manager); @@ -845,8 +839,7 @@ pub fn compile_no_check( file_map, noir_version: NOIR_ARTIFACT_VERSION_STRING.to_string(), warnings, - names, - brillig_names, + expression_width: options.expression_width.unwrap_or(DEFAULT_EXPRESSION_WIDTH), }) } diff --git a/compiler/noirc_driver/src/program.rs b/compiler/noirc_driver/src/program.rs index b3d545339fc..2febe6dcda3 100644 --- a/compiler/noirc_driver/src/program.rs +++ b/compiler/noirc_driver/src/program.rs @@ -1,6 +1,9 @@ use std::collections::BTreeMap; -use acvm::{FieldElement, acir::circuit::Program}; +use acvm::{ + FieldElement, + acir::circuit::{ExpressionWidth, Program}, +}; use fm::FileId; use noirc_errors::debug_info::DebugInfo; @@ -27,8 +30,6 @@ pub struct CompiledProgram { pub debug: Vec, pub file_map: BTreeMap, pub warnings: Vec, - /// Names of the functions in the program. These are used for more informative debugging and benchmarking. - pub names: Vec, - /// Names of the unconstrained functions in the program. - pub brillig_names: Vec, + /// Maximum width of the expressions which will be constrained + pub expression_width: ExpressionWidth, } diff --git a/compiler/noirc_evaluator/src/acir/acir_context/big_int.rs b/compiler/noirc_evaluator/src/acir/acir_context/big_int.rs deleted file mode 100644 index 8448b6efcba..00000000000 --- a/compiler/noirc_evaluator/src/acir/acir_context/big_int.rs +++ /dev/null @@ -1,57 +0,0 @@ -use acvm::acir::AcirField; -use num_bigint::BigUint; - -/// Represents a bigint value in the form (id, modulus) where -/// id is the identifier of the big integer number, and -/// modulus is the identifier of the big integer size -#[derive(Default, Clone, Copy, Debug)] -pub(super) struct BigIntId { - pub(super) bigint_id: u32, - pub(super) modulus_id: u32, -} - -impl BigIntId { - pub(super) fn bigint_id>(&self) -> F { - F::from(u128::from(self.bigint_id)) - } - - pub(super) fn modulus_id>(&self) -> F { - F::from(u128::from(self.modulus_id)) - } -} - -/// BigIntContext is used to generate identifiers for big integers and their modulus -#[derive(Default, Debug)] -pub(super) struct BigIntContext { - modulus: Vec, - big_integers: Vec, -} - -impl BigIntContext { - /// Creates a new BigIntId for the given modulus identifier and returns it. - pub(super) fn new_big_int(&mut self, modulus_id: F) -> BigIntId { - let id = self.big_integers.len() as u32; - let result = BigIntId { bigint_id: id, modulus_id: modulus_id.to_u128() as u32 }; - self.big_integers.push(result); - result - } - - /// Returns the modulus corresponding to the given modulus index - pub(super) fn modulus(&self, idx: F) -> BigUint { - self.modulus[idx.to_u128() as usize].clone() - } - - /// Returns the BigIntId corresponding to the given identifier - pub(super) fn get(&self, id: F) -> BigIntId { - self.big_integers[id.to_u128() as usize] - } - - /// Adds a modulus to the context (if it is not already present) - pub(super) fn get_or_insert_modulus(&mut self, modulus: BigUint) -> u32 { - if let Some(pos) = self.modulus.iter().position(|x| x == &modulus) { - return pos as u32; - } - self.modulus.push(modulus); - (self.modulus.len() - 1) as u32 - } -} diff --git a/compiler/noirc_evaluator/src/acir/acir_context/black_box.rs b/compiler/noirc_evaluator/src/acir/acir_context/black_box.rs index 45f349e7e68..bf4f5915cc0 100644 --- a/compiler/noirc_evaluator/src/acir/acir_context/black_box.rs +++ b/compiler/noirc_evaluator/src/acir/acir_context/black_box.rs @@ -1,13 +1,9 @@ -use acvm::acir::{ - AcirField, BlackBoxFunc, - circuit::opcodes::{ConstantOrWitnessEnum, FunctionInput}, -}; +use acvm::acir::{AcirField, BlackBoxFunc, circuit::opcodes::FunctionInput}; use iter_extended::vecmap; -use num_bigint::BigUint; use crate::errors::{InternalError, RuntimeError}; -use super::{AcirContext, AcirValue, AcirVar}; +use super::{AcirContext, AcirType, AcirValue, AcirVar}; impl AcirContext { /// Calls a Blackbox function on the given inputs and returns a given set of outputs @@ -16,121 +12,12 @@ impl AcirContext { &mut self, name: BlackBoxFunc, mut inputs: Vec, + num_bits: Option, mut output_count: usize, + predicate: Option, ) -> Result, RuntimeError> { // Separate out any arguments that should be constants - let (constant_inputs, constant_outputs) = match name { - BlackBoxFunc::Poseidon2Permutation => { - // The last argument is the state length, which must be a constant - let state_len = match inputs.pop() { - Some(state_len) => state_len.into_var()?, - None => { - return Err(RuntimeError::InternalError(InternalError::MissingArg { - name: "poseidon_2_permutation call".to_string(), - arg: "length".to_string(), - call_stack: self.get_call_stack(), - })); - } - }; - - let state_len = match self.var_to_expression(state_len)?.to_const() { - Some(state_len) => *state_len, - None => { - return Err(RuntimeError::InternalError(InternalError::NotAConstant { - name: "length".to_string(), - call_stack: self.get_call_stack(), - })); - } - }; - - (vec![state_len], Vec::new()) - } - BlackBoxFunc::BigIntAdd - | BlackBoxFunc::BigIntSub - | BlackBoxFunc::BigIntMul - | BlackBoxFunc::BigIntDiv => { - assert_eq!(inputs.len(), 4, "ICE - bigint operation requires 4 inputs"); - let const_inputs = vecmap(inputs, |i| { - let var = i.into_var()?; - match self.var_to_expression(var)?.to_const() { - Some(const_var) => Ok(*const_var), - None => Err(RuntimeError::InternalError(InternalError::NotAConstant { - name: "big integer".to_string(), - call_stack: self.get_call_stack(), - })), - } - }); - inputs = Vec::new(); - output_count = 0; - let mut field_inputs = Vec::new(); - for i in const_inputs { - field_inputs.push(i?); - } - if field_inputs[1] != field_inputs[3] { - return Err(RuntimeError::BigIntModulus { call_stack: self.get_call_stack() }); - } - - let result_id = self.big_int_ctx.new_big_int(field_inputs[1]); - ( - vec![field_inputs[0], field_inputs[2]], - vec![result_id.bigint_id::(), result_id.modulus_id::()], - ) - } - BlackBoxFunc::BigIntToLeBytes => { - let const_inputs = vecmap(inputs, |i| { - let var = i.into_var()?; - match self.var_to_expression(var)?.to_const() { - Some(const_var) => Ok(*const_var), - None => Err(RuntimeError::InternalError(InternalError::NotAConstant { - name: "big integer".to_string(), - call_stack: self.get_call_stack(), - })), - } - }); - inputs = Vec::new(); - let mut field_inputs = Vec::new(); - for i in const_inputs { - field_inputs.push(i?); - } - let bigint = self.big_int_ctx.get(field_inputs[0]); - let modulus = self.big_int_ctx.modulus(bigint.modulus_id::()); - let bytes_len = ((modulus - BigUint::from(1_u32)).bits() - 1) / 8 + 1; - output_count = bytes_len as usize; - assert!(bytes_len == 32); - (field_inputs, vec![]) - } - BlackBoxFunc::BigIntFromLeBytes => { - let invalid_input = "ICE - bigint operation requires 2 inputs"; - assert_eq!(inputs.len(), 2, "{invalid_input}"); - let mut modulus = Vec::new(); - match inputs.pop().expect(invalid_input) { - AcirValue::Array(values) => { - for value in values { - modulus.push( - *self.var_to_expression(value.into_var()?)?.to_const().ok_or( - RuntimeError::InternalError(InternalError::NotAConstant { - name: "big integer".to_string(), - call_stack: self.get_call_stack(), - }), - )?, - ); - } - } - _ => { - return Err(RuntimeError::InternalError(InternalError::MissingArg { - name: "big_int_from_le_bytes".to_owned(), - arg: "modulus".to_owned(), - call_stack: self.get_call_stack(), - })); - } - } - let big_modulus = BigUint::from_bytes_le(&vecmap(&modulus, |b| b.to_u128() as u8)); - output_count = 0; - - let modulus_id = self.big_int_ctx.get_or_insert_modulus(big_modulus); - let result_id = self.big_int_ctx.new_big_int(F::from(u128::from(modulus_id))); - (modulus, vec![result_id.bigint_id::(), result_id.modulus_id::()]) - } + let constant_inputs = match name { BlackBoxFunc::AES128Encrypt => { let invalid_input = "aes128_encrypt - operation requires a plaintext to encrypt"; let input_size: usize = match inputs.first().expect(invalid_input) { @@ -144,7 +31,7 @@ impl AcirContext { } }?; output_count = input_size + (16 - input_size % 16); - (vec![], vec![]) + Vec::new() } BlackBoxFunc::RecursiveAggregation => { let proof_type_var = match inputs.pop() { @@ -167,35 +54,26 @@ impl AcirContext { })); } }; - - (vec![proof_type_constant], Vec::new()) + inputs.push(AcirValue::Var(predicate.unwrap(), AcirType::unsigned(1))); + vec![proof_type_constant] } - _ => (vec![], vec![]), + _ => Vec::new(), }; let inputs = self.prepare_inputs_for_black_box_func(inputs, name)?; - // Call Black box with `FunctionInput` - let mut results = vecmap(&constant_outputs, |c| self.add_constant(*c)); let output_vars = vecmap(0..output_count, |_| self.add_variable()); let output_witnesses = vecmap(&output_vars, |var| { self.var_to_witness(*var).expect("variable was just created as witness") }); - self.acir_ir.call_black_box( - name, - &inputs, - constant_inputs, - constant_outputs, - output_witnesses, - )?; + self.acir_ir.call_black_box(name, &inputs, constant_inputs, num_bits, output_witnesses)?; // Convert `Witness` values which are now constrained to be the output of the // black box function call into `AcirVar`s. // // We do not apply range information on the output of the black box function. // See issue #1439 - results.extend(output_vars); - Ok(results) + Ok(output_vars) } pub(super) fn prepare_inputs_for_black_box_func( @@ -241,23 +119,20 @@ impl AcirContext { let num_bits = typ.bit_size::(); match self.var_to_expression(input)?.to_const() { Some(constant) if allow_constant_inputs => { - single_val_witnesses.push( - FunctionInput::constant(*constant, num_bits).map_err( - |invalid_input_bit_size| { - RuntimeError::InvalidBlackBoxInputBitSize { - value: invalid_input_bit_size.value, - num_bits: invalid_input_bit_size.value_num_bits, - max_num_bits: invalid_input_bit_size.max_bits, - call_stack: self.get_call_stack(), - } - }, - )?, - ); + if num_bits < constant.num_bits() { + return Err(RuntimeError::InvalidBlackBoxInputBitSize { + value: constant.to_string(), + num_bits: constant.num_bits(), + max_num_bits: num_bits, + call_stack: self.get_call_stack(), + }); + } + single_val_witnesses.push(FunctionInput::Constant(*constant)); } _ => { let witness_var = self.get_or_create_witness_var(input)?; let witness = self.var_to_witness(witness_var)?; - single_val_witnesses.push(FunctionInput::witness(witness, num_bits)); + single_val_witnesses.push(FunctionInput::Witness(witness)); } } } @@ -285,12 +160,11 @@ impl AcirContext { if has_constant && has_witness { // Convert the constants to witness if mixed constant and witness, for j in i - 2..i + 1 { - if let ConstantOrWitnessEnum::Constant(constant) = inputs[j][0].input() { + if let FunctionInput::Constant(constant) = inputs[j][0] { let constant = self.add_constant(constant); let witness_var = self.get_or_create_witness_var(constant)?; let witness = self.var_to_witness(witness_var)?; - result[j] = - vec![FunctionInput::witness(witness, inputs[j][0].num_bits())]; + result[j] = vec![FunctionInput::Witness(witness)]; } } } diff --git a/compiler/noirc_evaluator/src/acir/acir_context/generated_acir/mod.rs b/compiler/noirc_evaluator/src/acir/acir_context/generated_acir/mod.rs index 9fbc2f2e805..9e0bfb2e6b2 100644 --- a/compiler/noirc_evaluator/src/acir/acir_context/generated_acir/mod.rs +++ b/compiler/noirc_evaluator/src/acir/acir_context/generated_acir/mod.rs @@ -176,156 +176,158 @@ impl GeneratedAcir { pub(crate) fn call_black_box( &mut self, func_name: BlackBoxFunc, - inputs: &[Vec>], + function_inputs: &[Vec>], constant_inputs: Vec, - constant_outputs: Vec, + num_bits: Option, outputs: Vec, ) -> Result<(), InternalError> { - let input_count = inputs.iter().fold(0usize, |sum, val| sum + val.len()); + let input_count = function_inputs.iter().fold(0usize, |sum, val| sum + val.len()); intrinsics_check_inputs(func_name, input_count); intrinsics_check_outputs(func_name, outputs.len()); - let black_box_func_call = match func_name { BlackBoxFunc::AES128Encrypt => BlackBoxFuncCall::AES128Encrypt { - inputs: inputs[0].clone(), - iv: inputs[1] + inputs: function_inputs[0].clone(), + iv: function_inputs[1] .clone() .try_into() .expect("Compiler should generate correct size inputs"), - key: inputs[2] + key: function_inputs[2] .clone() .try_into() .expect("Compiler should generate correct size inputs"), outputs, }, - BlackBoxFunc::AND => { - BlackBoxFuncCall::AND { lhs: inputs[0][0], rhs: inputs[1][0], output: outputs[0] } - } - BlackBoxFunc::XOR => { - BlackBoxFuncCall::XOR { lhs: inputs[0][0], rhs: inputs[1][0], output: outputs[0] } - } - BlackBoxFunc::RANGE => BlackBoxFuncCall::RANGE { input: inputs[0][0] }, + BlackBoxFunc::AND => BlackBoxFuncCall::AND { + lhs: function_inputs[0][0], + rhs: function_inputs[1][0], + num_bits: num_bits.expect("missing num_bits"), + output: outputs[0], + }, + BlackBoxFunc::XOR => BlackBoxFuncCall::XOR { + lhs: function_inputs[0][0], + rhs: function_inputs[1][0], + num_bits: num_bits.expect("missing num_bits"), + output: outputs[0], + }, + BlackBoxFunc::RANGE => BlackBoxFuncCall::RANGE { + input: function_inputs[0][0], + num_bits: num_bits.expect("missing num_bits"), + }, BlackBoxFunc::Blake2s => BlackBoxFuncCall::Blake2s { - inputs: inputs[0].clone(), + inputs: function_inputs[0].clone(), outputs: outputs.try_into().expect("Compiler should generate correct size outputs"), }, BlackBoxFunc::Blake3 => BlackBoxFuncCall::Blake3 { - inputs: inputs[0].clone(), + inputs: function_inputs[0].clone(), outputs: outputs.try_into().expect("Compiler should generate correct size outputs"), }, BlackBoxFunc::EcdsaSecp256k1 => { + if function_inputs[0].len() != 32 + || function_inputs[1].len() != 32 + || function_inputs[2].len() != 64 + || function_inputs[3].len() != 32 + { + return Err(InternalError::General { + message: "Compiler should generate correct size inputs".to_string(), + call_stack: self.get_call_stack(), + }); + } BlackBoxFuncCall::EcdsaSecp256k1 { // 32 bytes for each public key co-ordinate - public_key_x: inputs[0] + public_key_x: function_inputs[0] .clone() .try_into() .expect("Compiler should generate correct size inputs"), - public_key_y: inputs[1] + public_key_y: function_inputs[1] .clone() .try_into() .expect("Compiler should generate correct size inputs"), // (r,s) are both 32 bytes each, so signature // takes up 64 bytes - signature: inputs[2] + signature: function_inputs[2] .clone() .try_into() .expect("Compiler should generate correct size inputs"), - hashed_message: inputs[3] + hashed_message: function_inputs[3] .clone() .try_into() .expect("Compiler should generate correct size inputs"), + predicate: function_inputs[4].clone()[0], output: outputs[0], } } BlackBoxFunc::EcdsaSecp256r1 => { BlackBoxFuncCall::EcdsaSecp256r1 { // 32 bytes for each public key co-ordinate - public_key_x: inputs[0] + public_key_x: function_inputs[0] .clone() .try_into() .expect("Compiler should generate correct size inputs"), - public_key_y: inputs[1] + public_key_y: function_inputs[1] + .clone() .clone() .try_into() .expect("Compiler should generate correct size inputs"), // (r,s) are both 32 bytes each, so signature // takes up 64 bytes - signature: inputs[2] + signature: function_inputs[2] .clone() .try_into() .expect("Compiler should generate correct size inputs"), - hashed_message: inputs[3] + hashed_message: function_inputs[3] .clone() .try_into() .expect("Compiler should generate correct size inputs"), + predicate: function_inputs[4].clone()[0], output: outputs[0], } } BlackBoxFunc::MultiScalarMul => BlackBoxFuncCall::MultiScalarMul { - points: inputs[0].clone(), - scalars: inputs[1].clone(), + points: function_inputs[0].clone(), + scalars: function_inputs[1].clone(), + predicate: function_inputs[2].clone()[0], outputs: (outputs[0], outputs[1], outputs[2]), }, BlackBoxFunc::EmbeddedCurveAdd => BlackBoxFuncCall::EmbeddedCurveAdd { - input1: Box::new([inputs[0][0], inputs[1][0], inputs[2][0]]), - input2: Box::new([inputs[3][0], inputs[4][0], inputs[5][0]]), + input1: Box::new([ + function_inputs[0].clone()[0], + function_inputs[1].clone()[0], + function_inputs[2].clone()[0], + ]), + input2: Box::new([ + function_inputs[3].clone()[0], + function_inputs[4].clone()[0], + function_inputs[5].clone()[0], + ]), + predicate: function_inputs[6].clone()[0], outputs: (outputs[0], outputs[1], outputs[2]), }, BlackBoxFunc::Keccakf1600 => BlackBoxFuncCall::Keccakf1600 { - inputs: inputs[0] + inputs: function_inputs[0] .clone() .try_into() .expect("Compiler should generate correct size inputs"), outputs: outputs.try_into().expect("Compiler should generate correct size outputs"), }, BlackBoxFunc::RecursiveAggregation => BlackBoxFuncCall::RecursiveAggregation { - verification_key: inputs[0].clone(), - proof: inputs[1].clone(), - public_inputs: inputs[2].clone(), - key_hash: inputs[3][0], + verification_key: function_inputs[0].clone(), + proof: function_inputs[1].clone(), + public_inputs: function_inputs[2].clone(), + key_hash: function_inputs[3].clone()[0], proof_type: constant_inputs[0].to_u128() as u32, - }, - BlackBoxFunc::BigIntAdd => BlackBoxFuncCall::BigIntAdd { - lhs: constant_inputs[0].to_u128() as u32, - rhs: constant_inputs[1].to_u128() as u32, - output: constant_outputs[0].to_u128() as u32, - }, - BlackBoxFunc::BigIntSub => BlackBoxFuncCall::BigIntSub { - lhs: constant_inputs[0].to_u128() as u32, - rhs: constant_inputs[1].to_u128() as u32, - output: constant_outputs[0].to_u128() as u32, - }, - BlackBoxFunc::BigIntMul => BlackBoxFuncCall::BigIntMul { - lhs: constant_inputs[0].to_u128() as u32, - rhs: constant_inputs[1].to_u128() as u32, - output: constant_outputs[0].to_u128() as u32, - }, - BlackBoxFunc::BigIntDiv => BlackBoxFuncCall::BigIntDiv { - lhs: constant_inputs[0].to_u128() as u32, - rhs: constant_inputs[1].to_u128() as u32, - output: constant_outputs[0].to_u128() as u32, - }, - BlackBoxFunc::BigIntFromLeBytes => BlackBoxFuncCall::BigIntFromLeBytes { - inputs: inputs[0].clone(), - modulus: vecmap(constant_inputs, |c| c.to_u128() as u8), - output: constant_outputs[0].to_u128() as u32, - }, - BlackBoxFunc::BigIntToLeBytes => BlackBoxFuncCall::BigIntToLeBytes { - input: constant_inputs[0].to_u128() as u32, - outputs, + predicate: function_inputs[4].clone()[0], }, BlackBoxFunc::Poseidon2Permutation => BlackBoxFuncCall::Poseidon2Permutation { - inputs: inputs[0].clone(), + inputs: function_inputs[0].clone(), outputs, - len: constant_inputs[0].to_u128() as u32, }, BlackBoxFunc::Sha256Compression => BlackBoxFuncCall::Sha256Compression { - inputs: inputs[0] + inputs: function_inputs[0] .clone() .try_into() .expect("Compiler should generate correct size inputs"), - hash_values: inputs[1] + hash_values: function_inputs[1] .clone() .try_into() .expect("Compiler should generate correct size inputs"), @@ -578,7 +580,8 @@ impl GeneratedAcir { }; let constraint = AcirOpcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { - input: FunctionInput::witness(witness, num_bits), + input: FunctionInput::Witness(witness), + num_bits, }); self.push_opcode(constraint); @@ -703,17 +706,8 @@ fn black_box_func_expected_input_size(name: BlackBoxFunc) -> Option { BlackBoxFunc::RecursiveAggregation => None, // Addition over the embedded curve: input are coordinates (x1,y1,infinite1) and (x2,y2,infinite2) of the Grumpkin points - BlackBoxFunc::EmbeddedCurveAdd => Some(6), - - // Big integer operations take in 0 inputs. They use constants for their inputs. - BlackBoxFunc::BigIntAdd - | BlackBoxFunc::BigIntSub - | BlackBoxFunc::BigIntMul - | BlackBoxFunc::BigIntDiv - | BlackBoxFunc::BigIntToLeBytes => Some(0), - - // FromLeBytes takes a variable array of bytes as input - BlackBoxFunc::BigIntFromLeBytes => None, + // to add, plus a predicate to conditionally perform the addition. + BlackBoxFunc::EmbeddedCurveAdd => Some(7), } } @@ -745,16 +739,6 @@ fn black_box_expected_output_size(name: BlackBoxFunc) -> Option { // will be 2 field elements representing the point. BlackBoxFunc::MultiScalarMul | BlackBoxFunc::EmbeddedCurveAdd => Some(3), - // Big integer operations return a big integer - BlackBoxFunc::BigIntAdd - | BlackBoxFunc::BigIntSub - | BlackBoxFunc::BigIntMul - | BlackBoxFunc::BigIntDiv - | BlackBoxFunc::BigIntFromLeBytes => Some(0), - - // ToLeBytes returns a variable array of bytes - BlackBoxFunc::BigIntToLeBytes => None, - // Recursive aggregation has a variable number of outputs BlackBoxFunc::RecursiveAggregation => None, diff --git a/compiler/noirc_evaluator/src/acir/acir_context/mod.rs b/compiler/noirc_evaluator/src/acir/acir_context/mod.rs index 0c46d5ab394..349397dd333 100644 --- a/compiler/noirc_evaluator/src/acir/acir_context/mod.rs +++ b/compiler/noirc_evaluator/src/acir/acir_context/mod.rs @@ -29,7 +29,6 @@ use crate::{ errors::{InternalBug, InternalError, RuntimeError, SsaReport}, }; -mod big_int; mod black_box; mod brillig_call; mod generated_acir; @@ -38,7 +37,6 @@ use super::{ AcirDynamicArray, AcirValue, types::{AcirType, AcirVar}, }; -use big_int::BigIntContext; pub use generated_acir::GeneratedAcir; pub(crate) use generated_acir::{BrilligStdLib, BrilligStdlibFunc}; @@ -63,9 +61,6 @@ pub(crate) struct AcirContext { /// addition. pub(super) acir_ir: GeneratedAcir, - /// The BigIntContext, used to generate identifiers for BigIntegers - big_int_ctx: BigIntContext, - expression_width: ExpressionWidth, pub(super) warnings: Vec, @@ -78,7 +73,6 @@ impl AcirContext { vars: Default::default(), constant_witnesses: Default::default(), acir_ir: Default::default(), - big_int_ctx: Default::default(), expression_width: Default::default(), warnings: Default::default(), } @@ -382,9 +376,10 @@ impl AcirContext { let sum = self.add_var(lhs, rhs)?; self.add_mul_var(sum, -F::from(2_u128), prod) } - NumericType::Signed { .. } | NumericType::Unsigned { .. } => { + NumericType::Signed { bit_size } | NumericType::Unsigned { bit_size } => { let inputs = vec![AcirValue::Var(lhs, typ.clone()), AcirValue::Var(rhs, typ)]; - let outputs = self.black_box_function(BlackBoxFunc::XOR, inputs, 1)?; + let outputs = + self.black_box_function(BlackBoxFunc::XOR, inputs, Some(bit_size), 1, None)?; Ok(outputs[0]) } NumericType::NativeField => { @@ -417,9 +412,10 @@ impl AcirContext { // Operands are booleans. self.mul_var(lhs, rhs) } - NumericType::Signed { .. } | NumericType::Unsigned { .. } => { + NumericType::Signed { bit_size } | NumericType::Unsigned { bit_size } => { let inputs = vec![AcirValue::Var(lhs, typ.clone()), AcirValue::Var(rhs, typ)]; - let outputs = self.black_box_function(BlackBoxFunc::AND, inputs, 1)?; + let outputs = + self.black_box_function(BlackBoxFunc::AND, inputs, Some(bit_size), 1, None)?; Ok(outputs[0]) } NumericType::NativeField => { @@ -1522,7 +1518,7 @@ impl AcirContext { // Add the memory read operation to the list of opcodes let op = MemOp::read_at_mem_index(index_witness.into(), value_read_witness); - self.acir_ir.push_opcode(Opcode::MemoryOp { block_id, op, predicate: None }); + self.acir_ir.push_opcode(Opcode::MemoryOp { block_id, op }); Ok(value_read_var) } @@ -1544,7 +1540,7 @@ impl AcirContext { // Add the memory write operation to the list of opcodes let op = MemOp::write_to_mem_index(index_witness.into(), value_write_witness.into()); - self.acir_ir.push_opcode(Opcode::MemoryOp { block_id, op, predicate: None }); + self.acir_ir.push_opcode(Opcode::MemoryOp { block_id, op }); Ok(()) } diff --git a/compiler/noirc_evaluator/src/acir/call.rs b/compiler/noirc_evaluator/src/acir/call.rs index e6b46a38891..611b5e4af48 100644 --- a/compiler/noirc_evaluator/src/acir/call.rs +++ b/compiler/noirc_evaluator/src/acir/call.rs @@ -191,34 +191,26 @@ impl Context<'_> { Ok(arguments.iter().map(|v| self.convert_value(*v, dfg)).collect()) } Intrinsic::BlackBox(black_box) => { - // Slices are represented as a tuple of (length, slice contents). - // We must check the inputs to determine if there are slices - // and make sure that we pass the correct inputs to the black box function call. - // The loop below only keeps the slice contents, so that - // setting up a black box function with slice inputs matches the expected - // number of arguments specified in the function signature. - let mut arguments_no_slice_len = Vec::new(); - for (i, arg) in arguments.iter().enumerate() { - if matches!(dfg.type_of_value(*arg), Type::Numeric(_)) { - if i < arguments.len() - 1 { - if !matches!(dfg.type_of_value(arguments[i + 1]), Type::Slice(_)) { - arguments_no_slice_len.push(*arg); - } - } else { - arguments_no_slice_len.push(*arg); - } - } else { - arguments_no_slice_len.push(*arg); - } - } + // Slice arguments to blackbox functions would break the following logic (due to being split over two `ValueIds`) + // No blackbox functions currently take slice arguments so we have an assertion here to catch if this changes in the future. + assert!( + !arguments.iter().any(|arg| matches!(dfg.type_of_value(*arg), Type::Slice(_))), + "ICE: Slice arguments passed to blackbox function" + ); - let inputs = vecmap(&arguments_no_slice_len, |arg| self.convert_value(*arg, dfg)); + let inputs = vecmap(arguments, |arg| self.convert_value(*arg, dfg)); let output_count = result_ids.iter().fold(0usize, |sum, result_id| { sum + dfg.type_of_value(*result_id).flattened_size() as usize }); - let vars = self.acir_context.black_box_function(black_box, inputs, output_count)?; + let vars = self.acir_context.black_box_function( + black_box, + inputs, + None, + output_count, + Some(self.current_side_effects_enabled_var), + )?; Ok(self.convert_vars_to_values(vars, dfg, result_ids)) } diff --git a/compiler/noirc_evaluator/src/acir/ssa.rs b/compiler/noirc_evaluator/src/acir/ssa.rs index 3c0840989c2..e1875a3ae74 100644 --- a/compiler/noirc_evaluator/src/acir/ssa.rs +++ b/compiler/noirc_evaluator/src/acir/ssa.rs @@ -17,7 +17,6 @@ use super::{Context, GeneratedAcir, SharedContext, acir_context::BrilligStdLib}; pub type Artifacts = ( Vec>, Vec>, - Vec, BTreeMap, ); @@ -88,10 +87,10 @@ pub(super) fn codegen_acir( } let generated_brillig = shared_context.finish(); - let (brillig_bytecode, brillig_names) = generated_brillig + let brillig_bytecode = generated_brillig .into_iter() - .map(|brillig| (BrilligBytecode { bytecode: brillig.byte_code }, brillig.name)) - .unzip(); + .map(|brillig| BrilligBytecode { function_name: brillig.name, bytecode: brillig.byte_code }) + .collect(); - Ok((acirs, brillig_bytecode, brillig_names, ssa.error_selector_to_type)) + Ok((acirs, brillig_bytecode, ssa.error_selector_to_type)) } diff --git a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs index 9402cf7bf07..e0cd71fc08c 100644 --- a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs @@ -149,24 +149,24 @@ fn multiple_brillig_stdlib_calls() { private parameters: [w0, w1, w2] public parameters: [] return values: [] - BLACKBOX::RANGE [(w0, 32)] [] - BLACKBOX::RANGE [(w1, 32)] [] - BLACKBOX::RANGE [(w2, 32)] [] + BLACKBOX::RANGE [w0]:32 bits [] + BLACKBOX::RANGE [w1]:32 bits [] + BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w1) 0 ]], outputs: [w3] EXPR [ (1, w1, w3) -1 ] BRILLIG CALL func 1: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w4, w5] - BLACKBOX::RANGE [(w4, 32)] [] - BLACKBOX::RANGE [(w5, 32)] [] + BLACKBOX::RANGE [w4]:32 bits [] + BLACKBOX::RANGE [w5]:32 bits [] EXPR [ (1, w1) (-1, w5) (-1, w6) -1 ] - BLACKBOX::RANGE [(w6, 32)] [] + BLACKBOX::RANGE [w6]:32 bits [] EXPR [ (-1, w1, w4) (1, w0) (-1, w5) 0 ] EXPR [ (-1, w2) (1, w4) 0 ] BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [w7] EXPR [ (1, w2, w7) -1 ] BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) 0 ], EXPR [ (1, w2) 0 ]], outputs: [w8, w9] - BLACKBOX::RANGE [(w9, 32)] [] + BLACKBOX::RANGE [w9]:32 bits [] EXPR [ (1, w2) (-1, w9) (-1, w10) -1 ] - BLACKBOX::RANGE [(w10, 32)] [] + BLACKBOX::RANGE [w10]:32 bits [] EXPR [ (-1, w2, w8) (1, w1) (-1, w9) 0 ] EXPR [ (1, w8) -1 ] @@ -237,28 +237,28 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { private parameters: [w0, w1, w2] public parameters: [] return values: [] - BLACKBOX::RANGE [(w0, 32)] [] - BLACKBOX::RANGE [(w1, 32)] [] - BLACKBOX::RANGE [(w2, 32)] [] + BLACKBOX::RANGE [w0]:32 bits [] + BLACKBOX::RANGE [w1]:32 bits [] + BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) 0 ]], outputs: [w3] EXPR [ (1, w1, w3) -1 ] BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w4, w5] - BLACKBOX::RANGE [(w4, 32)] [] - BLACKBOX::RANGE [(w5, 32)] [] + BLACKBOX::RANGE [w4]:32 bits [] + BLACKBOX::RANGE [w5]:32 bits [] EXPR [ (1, w1) (-1, w5) (-1, w6) -1 ] - BLACKBOX::RANGE [(w6, 32)] [] + BLACKBOX::RANGE [w6]:32 bits [] EXPR [ (-1, w1, w4) (1, w0) (-1, w5) 0 ] EXPR [ (-1, w2) (1, w4) 0 ] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w7] - BLACKBOX::RANGE [(w7, 32)] [] + BLACKBOX::RANGE [w7]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w8] - BLACKBOX::RANGE [(w8, 32)] [] + BLACKBOX::RANGE [w8]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w2) 0 ]], outputs: [w9] EXPR [ (1, w2, w9) -1 ] BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) 0 ], EXPR [ (1, w2) 0 ]], outputs: [w10, w11] - BLACKBOX::RANGE [(w11, 32)] [] + BLACKBOX::RANGE [w11]:32 bits [] EXPR [ (1, w2) (-1, w11) (-1, w12) -1 ] - BLACKBOX::RANGE [(w12, 32)] [] + BLACKBOX::RANGE [w12]:32 bits [] EXPR [ (-1, w2, w10) (1, w1) (-1, w11) 0 ] EXPR [ (1, w10) -1 ] @@ -371,30 +371,30 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { private parameters: [w0, w1, w2] public parameters: [] return values: [] - BLACKBOX::RANGE [(w0, 32)] [] - BLACKBOX::RANGE [(w1, 32)] [] - BLACKBOX::RANGE [(w2, 32)] [] + BLACKBOX::RANGE [w0]:32 bits [] + BLACKBOX::RANGE [w1]:32 bits [] + BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) 0 ]], outputs: [w3] EXPR [ (1, w1, w3) -1 ] BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w4, w5] - BLACKBOX::RANGE [(w4, 32)] [] - BLACKBOX::RANGE [(w5, 32)] [] + BLACKBOX::RANGE [w4]:32 bits [] + BLACKBOX::RANGE [w5]:32 bits [] EXPR [ (1, w1) (-1, w5) (-1, w6) -1 ] - BLACKBOX::RANGE [(w6, 32)] [] + BLACKBOX::RANGE [w6]:32 bits [] EXPR [ (-1, w1, w4) (1, w0) (-1, w5) 0 ] EXPR [ (-1, w2) (1, w4) 0 ] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w7] - BLACKBOX::RANGE [(w7, 32)] [] + BLACKBOX::RANGE [w7]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w8] - BLACKBOX::RANGE [(w8, 32)] [] + BLACKBOX::RANGE [w8]:32 bits [] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w9] BRILLIG CALL func 1: inputs: [EXPR [ (1, w2) 0 ]], outputs: [w10] EXPR [ (1, w2, w10) -1 ] BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) 0 ], EXPR [ (1, w2) 0 ]], outputs: [w11, w12] - BLACKBOX::RANGE [(w12, 32)] [] + BLACKBOX::RANGE [w12]:32 bits [] EXPR [ (1, w2) (-1, w12) (-1, w13) -1 ] - BLACKBOX::RANGE [(w13, 32)] [] + BLACKBOX::RANGE [w13]:32 bits [] EXPR [ (-1, w2, w11) (1, w1) (-1, w12) 0 ] EXPR [ (1, w11) -1 ] @@ -403,8 +403,8 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { private parameters: [w0, w1] public parameters: [] return values: [w2] - BLACKBOX::RANGE [(w0, 32)] [] - BLACKBOX::RANGE [(w1, 32)] [] + BLACKBOX::RANGE [w0]:32 bits [] + BLACKBOX::RANGE [w1]:32 bits [] EXPR [ (1, w0) (-1, w1) (-1, w3) 0 ] BRILLIG CALL func 1: inputs: [EXPR [ (1, w3) 0 ]], outputs: [w4] EXPR [ (1, w3, w4) (1, w5) -1 ] diff --git a/compiler/noirc_evaluator/src/acir/tests/intrinsics.rs b/compiler/noirc_evaluator/src/acir/tests/intrinsics.rs index 4c1e16e3ef1..0910337f794 100644 --- a/compiler/noirc_evaluator/src/acir/tests/intrinsics.rs +++ b/compiler/noirc_evaluator/src/acir/tests/intrinsics.rs @@ -155,7 +155,7 @@ fn get_slice_intrinsic_acir( let ssa = Ssa::from_str(&src).unwrap(); let brillig = ssa.to_brillig(&BrilligOptions::default()); - let (acir_functions_with_pred, _brillig_functions, _, _) = ssa + let (acir_functions_with_pred, _brillig_functions, _) = ssa .into_acir(&brillig, &BrilligOptions::default(), ExpressionWidth::default()) .expect("Should compile manually written SSA into ACIR"); acir_functions_with_pred diff --git a/compiler/noirc_evaluator/src/acir/tests/mod.rs b/compiler/noirc_evaluator/src/acir/tests/mod.rs index 8e59605565e..3a43b6394e4 100644 --- a/compiler/noirc_evaluator/src/acir/tests/mod.rs +++ b/compiler/noirc_evaluator/src/acir/tests/mod.rs @@ -55,14 +55,13 @@ fn ssa_to_acir_program_with_debug_info(src: &str) -> (Program, Vec let brillig = ssa.to_brillig(&BrilligOptions::default()); - let (acir_functions, brillig_functions, brillig_names, _) = ssa + let (acir_functions, brillig_functions, _) = ssa + .generate_entry_point_index() .into_acir(&brillig, &BrilligOptions::default(), ExpressionWidth::default()) .expect("Should compile manually written SSA into ACIR"); - let artifacts = ArtifactsAndWarnings( - (acir_functions, brillig_functions, brillig_names, BTreeMap::default()), - vec![], - ); + let artifacts = + ArtifactsAndWarnings((acir_functions, brillig_functions, BTreeMap::default()), vec![]); let program_artifact = combine_artifacts( artifacts, &arg_size_and_visibilities, @@ -93,8 +92,8 @@ fn unchecked_mul_should_not_have_range_check() { private parameters: [w0, w1] public parameters: [] return values: [w2] - BLACKBOX::RANGE [(w0, 32)] [] - BLACKBOX::RANGE [(w1, 32)] [] + BLACKBOX::RANGE [w0]:32 bits [] + BLACKBOX::RANGE [w1]:32 bits [] EXPR [ (-1, w0, w1) (1, w2) 0 ] "); } @@ -259,7 +258,7 @@ fn properly_constrains_quotient_when_truncating_fields() { let malicious_brillig_stdlib = BrilligStdLib { quotient: malicious_quotient, ..BrilligStdLib::default() }; - let (acir_functions, brillig_functions, _, _) = codegen_acir( + let (acir_functions, brillig_functions, _) = codegen_acir( ssa, &Brillig::default(), malicious_brillig_stdlib, @@ -302,7 +301,7 @@ fn do_not_overflow_with_constant_constrain_neq() { let ssa = Ssa::from_str(src).unwrap(); let brillig = ssa.to_brillig(&BrilligOptions::default()); - let (acir_functions, _brillig_functions, _, _) = ssa + let (acir_functions, _brillig_functions, _) = ssa .into_acir(&brillig, &BrilligOptions::default(), ExpressionWidth::default()) .expect("Should compile manually written SSA into ACIR"); @@ -364,7 +363,7 @@ fn execute_ssa( output: Option<&Witness>, ) -> (ACVMStatus, Option) { let brillig = ssa.to_brillig(&BrilligOptions::default()); - let (acir_functions, brillig_functions, _, _) = ssa + let (acir_functions, brillig_functions, _) = ssa .into_acir(&brillig, &BrilligOptions::default(), ExpressionWidth::default()) .expect("Should compile manually written SSA into ACIR"); assert_eq!(acir_functions.len(), 1); diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs index 818bc96bcfa..52f803269a9 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs @@ -218,138 +218,9 @@ pub(crate) fn convert_black_box_call {} - BlackBoxFunc::BigIntAdd => { - if let ( - [ - BrilligVariable::SingleAddr(lhs), - BrilligVariable::SingleAddr(_lhs_modulus), - BrilligVariable::SingleAddr(rhs), - BrilligVariable::SingleAddr(_rhs_modulus), - ], - [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(_modulus_id)], - ) = (function_arguments, function_results) - { - brillig_context.black_box_op_instruction(BlackBoxOp::BigIntAdd { - lhs: lhs.address, - rhs: rhs.address, - output: output.address, - }); - } else { - unreachable!( - "ICE: BigIntAdd expects four register arguments and two result registers" - ) - } - } - BlackBoxFunc::BigIntSub => { - if let ( - [ - BrilligVariable::SingleAddr(lhs), - BrilligVariable::SingleAddr(_lhs_modulus), - BrilligVariable::SingleAddr(rhs), - BrilligVariable::SingleAddr(_rhs_modulus), - ], - [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(_modulus_id)], - ) = (function_arguments, function_results) - { - brillig_context.black_box_op_instruction(BlackBoxOp::BigIntSub { - lhs: lhs.address, - rhs: rhs.address, - output: output.address, - }); - } else { - unreachable!( - "ICE: BigIntSub expects four register arguments and two result registers" - ) - } - } - BlackBoxFunc::BigIntMul => { - if let ( - [ - BrilligVariable::SingleAddr(lhs), - BrilligVariable::SingleAddr(_lhs_modulus), - BrilligVariable::SingleAddr(rhs), - BrilligVariable::SingleAddr(_rhs_modulus), - ], - [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(_modulus_id)], - ) = (function_arguments, function_results) - { - brillig_context.black_box_op_instruction(BlackBoxOp::BigIntMul { - lhs: lhs.address, - rhs: rhs.address, - output: output.address, - }); - } else { - unreachable!( - "ICE: BigIntMul expects four register arguments and two result registers" - ) - } - } - BlackBoxFunc::BigIntDiv => { - if let ( - [ - BrilligVariable::SingleAddr(lhs), - BrilligVariable::SingleAddr(_lhs_modulus), - BrilligVariable::SingleAddr(rhs), - BrilligVariable::SingleAddr(_rhs_modulus), - ], - [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(_modulus_id)], - ) = (function_arguments, function_results) - { - brillig_context.black_box_op_instruction(BlackBoxOp::BigIntDiv { - lhs: lhs.address, - rhs: rhs.address, - output: output.address, - }); - } else { - unreachable!( - "ICE: BigIntDiv expects four register arguments and two result registers" - ) - } - } - BlackBoxFunc::BigIntFromLeBytes => { - if let ( - [inputs, modulus], - [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(_modulus_id)], - ) = (function_arguments, function_results) - { - let inputs = convert_array_or_vector(brillig_context, *inputs, bb_func); - let modulus = convert_array_or_vector(brillig_context, *modulus, bb_func); - brillig_context.black_box_op_instruction(BlackBoxOp::BigIntFromLeBytes { - inputs, - modulus, - output: output.address, - }); - brillig_context.deallocate_heap_vector(inputs); - brillig_context.deallocate_heap_vector(modulus); - } else { - unreachable!( - "ICE: BigIntFromLeBytes expects a register and an array as arguments and two result registers" - ) - } - } - BlackBoxFunc::BigIntToLeBytes => { - if let ( - [BrilligVariable::SingleAddr(input), BrilligVariable::SingleAddr(_modulus)], - [output], - ) = (function_arguments, function_results) - { - let output = convert_array_or_vector(brillig_context, *output, bb_func); - brillig_context.black_box_op_instruction(BlackBoxOp::BigIntToLeBytes { - input: input.address, - output, - }); - brillig_context.deallocate_heap_vector(output); - } else { - unreachable!( - "ICE: BigIntToLeBytes expects two register arguments and one array result" - ) - } - } BlackBoxFunc::Poseidon2Permutation => { - if let ( - [message, BrilligVariable::SingleAddr(state_len)], - [BrilligVariable::BrilligArray(result_array)], - ) = (function_arguments, function_results) + if let ([message], [BrilligVariable::BrilligArray(result_array)]) = + (function_arguments, function_results) { let message_vector = convert_array_or_vector(brillig_context, *message, bb_func); let output_heap_array = @@ -358,7 +229,6 @@ pub(crate) fn convert_black_box_call BrilligBlock<'block, Registers> { } } + if matches!( + bb_func, + BlackBoxFunc::EcdsaSecp256k1 + | BlackBoxFunc::EcdsaSecp256r1 + | BlackBoxFunc::MultiScalarMul + | BlackBoxFunc::EmbeddedCurveAdd + ) { + // Some black box functions have a predicate argument in SSA which we don't want to + // use in the brillig VM. This is as we do not need to flatten the CFG in brillig + // so we expect the predicate to always be true. + let predicate = &arguments_no_slice_len.pop().expect( + "ICE: ECDSA black box function must have a predicate argument", + ); + assert_eq!( + dfg.get_numeric_constant_with_type(*predicate), + Some((FieldElement::one(), NumericType::bool())), + "ICE: ECDSA black box function must have a predicate argument with value 1" + ); + } + let function_arguments = vecmap(&arguments_no_slice_len, |arg| { self.convert_ssa_value(*arg, dfg) }); diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs index 1ce2b988aa9..6a44db059b4 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs @@ -379,7 +379,6 @@ pub(crate) mod tests { fn poseidon2_permutation( &self, _inputs: &[FieldElement], - _len: u32, ) -> Result, BlackBoxResolutionError> { Ok(vec![0_u128.into(), 1_u128.into(), 2_u128.into(), 3_u128.into()]) } diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs index 60be427c275..ea760ae8fbc 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs @@ -268,12 +268,7 @@ impl BrilligArtifact { /// Returns true if the opcode is a jump instruction fn is_jmp_instruction(instruction: &BrilligOpcode) -> bool { - matches!( - instruction, - BrilligOpcode::JumpIfNot { .. } - | BrilligOpcode::JumpIf { .. } - | BrilligOpcode::Jump { .. } - ) + matches!(instruction, BrilligOpcode::JumpIf { .. } | BrilligOpcode::Jump { .. }) } /// Adds a label in the bytecode to specify where this block's @@ -313,15 +308,6 @@ impl BrilligArtifact { self.byte_code[*location_of_jump] = BrilligOpcode::Jump { location: resolved_location }; } - BrilligOpcode::JumpIfNot { condition, location } => { - assert_eq!( - location, 0, - "location is not zero, which means that the jump label does not need resolving" - ); - - self.byte_code[*location_of_jump] = - BrilligOpcode::JumpIfNot { condition, location: resolved_location }; - } BrilligOpcode::JumpIf { condition, location } => { assert_eq!( location, 0, diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs index f68143e5bb9..329325f22e2 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs @@ -344,65 +344,11 @@ impl DebugShow { result ); } - BlackBoxOp::BigIntAdd { lhs, rhs, output } => { + BlackBoxOp::Poseidon2Permutation { message, output } => { debug_println!( self.enable_debug_trace, - " BIGINT_ADD {} {} -> {}", - lhs, - rhs, - output - ); - } - BlackBoxOp::BigIntSub { lhs, rhs, output } => { - debug_println!( - self.enable_debug_trace, - " BIGINT_NEG {} {} -> {}", - lhs, - rhs, - output - ); - } - BlackBoxOp::BigIntMul { lhs, rhs, output } => { - debug_println!( - self.enable_debug_trace, - " BIGINT_MUL {} {} -> {}", - lhs, - rhs, - output - ); - } - BlackBoxOp::BigIntDiv { lhs, rhs, output } => { - debug_println!( - self.enable_debug_trace, - " BIGINT_DIV {} {} -> {}", - lhs, - rhs, - output - ); - } - BlackBoxOp::BigIntFromLeBytes { inputs, modulus, output } => { - debug_println!( - self.enable_debug_trace, - " BIGINT_FROM_LE_BYTES {} {} -> {}", - inputs, - modulus, - output - ); - } - BlackBoxOp::BigIntToLeBytes { input, output } => { - debug_println!( - self.enable_debug_trace, - " BIGINT_TO_LE_BYTES {} -> {}", - input, - output - ); - } - BlackBoxOp::Poseidon2Permutation { message, output, len } => { - debug_println!( - self.enable_debug_trace, - " POSEIDON2_PERMUTATION {} {} -> {}", + " POSEIDON2_PERMUTATION {} -> {}", message, - len, output ); } diff --git a/compiler/noirc_evaluator/src/ssa/artifact.rs b/compiler/noirc_evaluator/src/ssa/artifact.rs index 78e1dac2204..2ed20a11efe 100644 --- a/compiler/noirc_evaluator/src/ssa/artifact.rs +++ b/compiler/noirc_evaluator/src/ssa/artifact.rs @@ -13,29 +13,18 @@ pub struct SsaProgramArtifact { pub program: Program, pub debug: Vec, pub warnings: Vec, - pub names: Vec, - pub brillig_names: Vec, pub error_types: BTreeMap, } impl SsaProgramArtifact { pub fn new( functions: Vec, - brillig_names: Vec, unconstrained_functions: Vec>, error_types: BTreeMap, warnings: Vec, ) -> Self { - assert_eq!(brillig_names.len(), unconstrained_functions.len()); let program = Program { functions: Vec::default(), unconstrained_functions }; - let mut this = Self { - program, - debug: Vec::default(), - warnings, - names: Vec::default(), - brillig_names, - error_types, - }; + let mut this = Self { program, debug: Vec::default(), warnings, error_types }; for function in functions { this.add_circuit(function); @@ -48,7 +37,6 @@ impl SsaProgramArtifact { self.program.functions.push(circuit_artifact.circuit); self.debug.push(circuit_artifact.debug_info); self.warnings.append(&mut circuit_artifact.warnings); - self.names.push(circuit_artifact.name); // Acir and brillig both generate new error types, so we need to merge them // With the ones found during ssa generation. self.error_types.extend(circuit_artifact.error_types); diff --git a/compiler/noirc_evaluator/src/ssa/interpreter/intrinsics.rs b/compiler/noirc_evaluator/src/ssa/interpreter/intrinsics.rs index 8902020f351..371919bb524 100644 --- a/compiler/noirc_evaluator/src/ssa/interpreter/intrinsics.rs +++ b/compiler/noirc_evaluator/src/ssa/interpreter/intrinsics.rs @@ -164,11 +164,12 @@ impl Interpreter<'_, W> { Ok(vec![results]) } acvm::acir::BlackBoxFunc::EcdsaSecp256k1 => { - check_argument_count(args, 4, intrinsic)?; + check_argument_count(args, 5, intrinsic)?; let x = self.lookup_bytes(args[0], "call EcdsaSecp256k1 BlackBox")?; let y = self.lookup_bytes(args[1], "call EcdsaSecp256k1 BlackBox")?; let s = self.lookup_bytes(args[2], "call EcdsaSecp256k1 BlackBox")?; let m = self.lookup_bytes(args[3], "call EcdsaSecp256k1 BlackBox")?; + let predicate = self.lookup_bool(args[4], "call EcdsaSecp256k1 BlackBox")?; let x_len = x.len(); let x_array: &[u8; 32] = &x.try_into().map_err(|_| { InterpreterError::Internal(InternalError::InvalidInputSize { @@ -190,21 +191,24 @@ impl Interpreter<'_, W> { size: s_len, }) })?; - let result = acvm::blackbox_solver::ecdsa_secp256k1_verify( - &m, x_array, y_array, s_array, - ) - .map_err(Self::convert_error)?; + let result = if predicate { + acvm::blackbox_solver::ecdsa_secp256k1_verify(&m, x_array, y_array, s_array) + .map_err(Self::convert_error)? + } else { + true + }; Ok(vec![Value::from_constant( result.into(), NumericType::Unsigned { bit_size: 1 }, )?]) } acvm::acir::BlackBoxFunc::EcdsaSecp256r1 => { - check_argument_count(args, 4, intrinsic)?; + check_argument_count(args, 5, intrinsic)?; let x = self.lookup_bytes(args[0], "call EcdsaSecp256r1 BlackBox")?; let y = self.lookup_bytes(args[1], "call EcdsaSecp256r1 BlackBox")?; let s = self.lookup_bytes(args[2], "call EcdsaSecp256r1 BlackBox")?; let m = self.lookup_bytes(args[3], "call EcdsaSecp256r1 BlackBox")?; + let predicate = self.lookup_bool(args[4], "call EcdsaSecp256r1 BlackBox")?; let x_len = x.len(); let x_array: &[u8; 32] = &x.try_into().map_err(|_| { InterpreterError::Internal(InternalError::InvalidInputSize { @@ -226,17 +230,20 @@ impl Interpreter<'_, W> { size: s_len, }) })?; - let result = acvm::blackbox_solver::ecdsa_secp256r1_verify( - &m, x_array, y_array, s_array, - ) - .map_err(Self::convert_error)?; + + let result = if predicate { + acvm::blackbox_solver::ecdsa_secp256r1_verify(&m, x_array, y_array, s_array) + .map_err(Self::convert_error)? + } else { + true + }; Ok(vec![Value::from_constant( result.into(), NumericType::Unsigned { bit_size: 1 }, )?]) } acvm::acir::BlackBoxFunc::MultiScalarMul => { - check_argument_count(args, 2, intrinsic)?; + check_argument_count(args, 3, intrinsic)?; let input_points = self.lookup_array_or_slice(args[0], "call to MultiScalarMul blackbox")?; let mut points = Vec::new(); @@ -316,7 +323,7 @@ impl Interpreter<'_, W> { Ok(vec![]) } acvm::acir::BlackBoxFunc::EmbeddedCurveAdd => { - check_argument_count(args, 6, intrinsic)?; + check_argument_count(args, 7, intrinsic)?; let solver = bn254_blackbox_solver::Bn254BlackBoxSolver(false); let lhs = ( self.lookup_field(args[0], "call EmbeddedCurveAdd BlackBox")?, @@ -334,26 +341,14 @@ impl Interpreter<'_, W> { let result = new_embedded_curve_point(x, y, is_infinite)?; Ok(vec![result]) } - acvm::acir::BlackBoxFunc::BigIntAdd - | acvm::acir::BlackBoxFunc::BigIntSub - | acvm::acir::BlackBoxFunc::BigIntMul - | acvm::acir::BlackBoxFunc::BigIntDiv - | acvm::acir::BlackBoxFunc::BigIntFromLeBytes - | acvm::acir::BlackBoxFunc::BigIntToLeBytes => { - Err(InterpreterError::Internal(InternalError::UnexpectedInstruction { - reason: "unused BigInt BlackBox function", - })) - } + acvm::acir::BlackBoxFunc::Poseidon2Permutation => { - check_argument_count(args, 2, intrinsic)?; + check_argument_count(args, 1, intrinsic)?; let inputs = self .lookup_vec_field(args[0], "call Poseidon2Permutation BlackBox (inputs)")?; - let length = - self.lookup_u32(args[1], "call Poseidon2Permutation BlackBox (length)")?; let solver = bn254_blackbox_solver::Bn254BlackBoxSolver(false); - let result = solver - .poseidon2_permutation(&inputs, length) - .map_err(Self::convert_error)?; + let result = + solver.poseidon2_permutation(&inputs).map_err(Self::convert_error)?; let result = Value::array_from_iter(result, NumericType::NativeField)?; Ok(vec![result]) } diff --git a/compiler/noirc_evaluator/src/ssa/interpreter/tests/black_box.rs b/compiler/noirc_evaluator/src/ssa/interpreter/tests/black_box.rs index 142f1b24e90..6eef1eb24f6 100644 --- a/compiler/noirc_evaluator/src/ssa/interpreter/tests/black_box.rs +++ b/compiler/noirc_evaluator/src/ssa/interpreter/tests/black_box.rs @@ -10,7 +10,7 @@ fn test_msm() { b0(v0: Field, v1: Field): v2 = make_array [Field 1, Field 17631683881184975370165255887551781615748388533673675138860, u1 0] : [(Field, Field, u1); 1] v3 = make_array [v0, v1] : [(Field, Field); 1] - v4= call multi_scalar_mul(v2, v3) -> [(Field, Field, u1); 1] + v4= call multi_scalar_mul(v2, v3, u1 1) -> [(Field, Field, u1); 1] return v4 } "; @@ -30,7 +30,7 @@ fn test_ec_add() { let src = " acir(inline) fn main f0 { b0(v0: Field): - v1 = call embedded_curve_add(v0, Field 17631683881184975370165255887551781615748388533673675138860, u1 0, v0, Field 17631683881184975370165255887551781615748388533673675138860, u1 0) -> [(Field, Field, u1); 1] + v1 = call embedded_curve_add(v0, Field 17631683881184975370165255887551781615748388533673675138860, u1 0, v0, Field 17631683881184975370165255887551781615748388533673675138860, u1 0, u1 1) -> [(Field, Field, u1); 1] return v1 } "; @@ -159,7 +159,7 @@ fn test_poseidon() { let src = " acir(inline) predicate_pure fn main f0 { b0(v0: [Field; 4]): - v1 = call poseidon2_permutation(v0, u32 4) -> [Field; 4] + v1 = call poseidon2_permutation(v0) -> [Field; 4] return v1 } "; @@ -193,7 +193,7 @@ fn test_ecdsa_k1() { let src = " acir(inline) predicate_pure fn main f0 { b0(v0: [u8; 32], v1: [u8; 32], v2: [u8; 64], v3: [u8; 32]): - v4 = call ecdsa_secp256k1(v0, v1, v2, v3) -> u1 + v4 = call ecdsa_secp256k1(v0, v1, v2, v3, u1 1) -> u1 return v4 } "; @@ -240,7 +240,7 @@ fn test_ecdsa_r1() { let src = " acir(inline) predicate_pure fn main f0 { b0(v0: [u8; 32], v1: [u8; 32], v2: [u8; 64], v3: [u8; 32]): - v4 = call ecdsa_secp256r1(v0, v1, v2, v3) -> u1 + v4 = call ecdsa_secp256r1(v0, v1, v2, v3, u1 1) -> u1 return v4 } "; diff --git a/compiler/noirc_evaluator/src/ssa/ir/dfg/simplify/call.rs b/compiler/noirc_evaluator/src/ssa/ir/dfg/simplify/call.rs index 17c8b076d82..f446b90e1dc 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/dfg/simplify/call.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/dfg/simplify/call.rs @@ -670,13 +670,7 @@ fn simplify_black_box_func( blackbox::simplify_ec_add(dfg, solver, arguments, block, call_stack) } - BlackBoxFunc::BigIntAdd - | BlackBoxFunc::BigIntSub - | BlackBoxFunc::BigIntMul - | BlackBoxFunc::BigIntDiv - | BlackBoxFunc::RecursiveAggregation - | BlackBoxFunc::BigIntFromLeBytes - | BlackBoxFunc::BigIntToLeBytes => SimplifyResult::None, + BlackBoxFunc::RecursiveAggregation => SimplifyResult::None, BlackBoxFunc::AND => { unreachable!("ICE: `BlackBoxFunc::AND` calls should be transformed into a `BinaryOp`") diff --git a/compiler/noirc_evaluator/src/ssa/ir/dfg/simplify/call/blackbox.rs b/compiler/noirc_evaluator/src/ssa/ir/dfg/simplify/call/blackbox.rs index d80f49b4119..829599f10ce 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/dfg/simplify/call/blackbox.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/dfg/simplify/call/blackbox.rs @@ -75,7 +75,7 @@ pub(super) fn simplify_msm( call_stack: CallStackId, ) -> SimplifyResult { let mut is_constant; - + let predicate = arguments[2]; match (dfg.get_array_constant(arguments[0]), dfg.get_array_constant(arguments[1])) { (Some((points, _)), Some((scalars, _))) => { // We decompose points and scalars into constant and non-constant parts in order to simplify MSMs where a subset of the terms are constant. @@ -197,7 +197,7 @@ pub(super) fn simplify_msm( let msm = dfg.import_intrinsic(Intrinsic::BlackBox(BlackBoxFunc::MultiScalarMul)); SimplifyResult::SimplifiedToInstruction(Instruction::Call { func: msm, - arguments: vec![points, scalars], + arguments: vec![points, scalars, predicate], }) } _ => SimplifyResult::None, @@ -211,8 +211,8 @@ pub(super) fn simplify_poseidon2_permutation( block: BasicBlockId, call_stack: CallStackId, ) -> SimplifyResult { - match (dfg.get_array_constant(arguments[0]), dfg.get_numeric_constant(arguments[1])) { - (Some((state, _)), Some(state_length)) if array_is_constant(dfg, &state) => { + match dfg.get_array_constant(arguments[0]) { + Some((state, _)) if array_is_constant(dfg, &state) => { let state: Vec = state .iter() .map(|id| { @@ -221,11 +221,7 @@ pub(super) fn simplify_poseidon2_permutation( }) .collect(); - let Some(state_length) = state_length.try_to_u32() else { - return SimplifyResult::None; - }; - - let Ok(new_state) = solver.poseidon2_permutation(&state, state_length) else { + let Ok(new_state) = solver.poseidon2_permutation(&state) else { return SimplifyResult::None; }; @@ -329,17 +325,23 @@ pub(super) fn simplify_signature( dfg.get_array_constant(arguments[1]), dfg.get_array_constant(arguments[2]), dfg.get_array_constant(arguments[3]), + dfg.get_array_constant(arguments[4]), ) { ( Some((public_key_x, _)), Some((public_key_y, _)), Some((signature, _)), Some((hashed_message, _)), + Some((predicate, _)), ) if array_is_constant(dfg, &public_key_x) && array_is_constant(dfg, &public_key_y) && array_is_constant(dfg, &signature) && array_is_constant(dfg, &hashed_message) => { + if dfg.get_numeric_constant(predicate[0]) == Some(FieldElement::zero()) { + let valid_signature = dfg.make_constant(1_u128.into(), NumericType::bool()); + return SimplifyResult::SimplifiedTo(valid_signature); + } let public_key_x: [u8; 32] = to_u8_vec(dfg, public_key_x) .try_into() .expect("ECDSA public key fields are 32 bytes"); @@ -375,7 +377,7 @@ mod multi_scalar_mul { b0(): v0 = make_array [Field 2, Field 3, Field 5, Field 5] : [(Field, Field); 2] v1 = make_array [Field 1, Field 17631683881184975370165255887551781615748388533673675138860, u1 0, Field 1, Field 17631683881184975370165255887551781615748388533673675138860, u1 0] : [(Field, Field, u1); 2] - v2 = call multi_scalar_mul (v1, v0) -> [(Field, Field, u1); 1] + v2 = call multi_scalar_mul (v1, v0, u1 1) -> [(Field, Field, u1); 1] return v2 }"#; let ssa = Ssa::from_str_simplifying(src).unwrap(); @@ -400,7 +402,7 @@ mod multi_scalar_mul { v2 = make_array [v0, Field 0, Field 0, Field 0, v0, Field 0] : [(Field, Field); 3] v3 = make_array [ Field 0, Field 0, u1 1, v0, v1, u1 0, Field 1, v0, u1 0] : [(Field, Field, u1); 3] - v4 = call multi_scalar_mul (v3, v2) -> [(Field, Field, u1); 1] + v4 = call multi_scalar_mul (v3, v2, u1 1) -> [(Field, Field, u1); 1] return v4 @@ -414,7 +416,7 @@ mod multi_scalar_mul { v7 = make_array [Field 0, Field 0, u1 1, v0, v1, u1 0, Field 1, v0, u1 0] : [(Field, Field, u1); 3] v8 = make_array [v0, Field 0] : [(Field, Field); 1] v9 = make_array [Field 1, v0, u1 0] : [(Field, Field, u1); 1] - v11 = call multi_scalar_mul(v9, v8) -> [(Field, Field, u1); 1] + v11 = call multi_scalar_mul(v9, v8, u1 1) -> [(Field, Field, u1); 1] return v11 } "); @@ -429,7 +431,7 @@ mod multi_scalar_mul { v2 = make_array [Field 1, Field 0, v0, Field 0, Field 2, Field 0] : [(Field, Field); 3] v3 = make_array [ Field 1, Field 17631683881184975370165255887551781615748388533673675138860, u1 0, v0, v1, u1 0, Field 1, Field 17631683881184975370165255887551781615748388533673675138860, u1 0] : [(Field, Field, u1); 3] - v4 = call multi_scalar_mul (v3, v2) -> [(Field, Field, u1); 1] + v4 = call multi_scalar_mul (v3, v2, u1 1) -> [(Field, Field, u1); 1] return v4 }"#; let ssa = Ssa::from_str_simplifying(src).unwrap(); @@ -441,8 +443,8 @@ mod multi_scalar_mul { v8 = make_array [Field 1, Field 17631683881184975370165255887551781615748388533673675138860, u1 0, v0, v1, u1 0, Field 1, Field 17631683881184975370165255887551781615748388533673675138860, u1 0] : [(Field, Field, u1); 3] v9 = make_array [v0, Field 0, Field 1, Field 0] : [(Field, Field); 2] v12 = make_array [v0, v1, u1 0, Field -3227352362257037263902424173275354266044964400219754872043023745437788450996, Field 8902249110305491597038405103722863701255802573786510474664632793109847672620, u1 0] : [(Field, Field, u1); 2] - v14 = call multi_scalar_mul(v12, v9) -> [(Field, Field, u1); 1] - return v14 + v15 = call multi_scalar_mul(v12, v9, u1 1) -> [(Field, Field, u1); 1] + return v15 } "); } diff --git a/compiler/noirc_evaluator/src/ssa/mod.rs b/compiler/noirc_evaluator/src/ssa/mod.rs index 76e01a9fc35..9b239e3b2dc 100644 --- a/compiler/noirc_evaluator/src/ssa/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/mod.rs @@ -408,10 +408,8 @@ pub fn combine_artifacts( debug_functions: DebugFunctions, debug_types: DebugTypes, ) -> SsaProgramArtifact { - let ArtifactsAndWarnings( - (generated_acirs, generated_brillig, brillig_function_names, error_types), - ssa_level_warnings, - ) = artifacts; + let ArtifactsAndWarnings((generated_acirs, generated_brillig, error_types), ssa_level_warnings) = + artifacts; assert_eq!( generated_acirs.len(), @@ -438,13 +436,7 @@ pub fn combine_artifacts( .map(|(selector, hir_type)| (selector, ErrorType::Dynamic(hir_type))) .collect(); - SsaProgramArtifact::new( - functions, - brillig_function_names, - generated_brillig, - error_types, - ssa_level_warnings, - ) + SsaProgramArtifact::new(functions, generated_brillig, error_types, ssa_level_warnings) } fn resolve_function_signature(func_sig: &FunctionSignature) -> Vec<(u32, Visibility)> { @@ -483,8 +475,8 @@ pub fn convert_generated_acir_into_circuit( let return_values = PublicInputs(return_witnesses.iter().copied().collect()); let circuit = Circuit { + function_name: name.clone(), current_witness_index, - expression_width: ExpressionWidth::Unbounded, opcodes, private_parameters, public_parameters, diff --git a/compiler/noirc_evaluator/src/ssa/opt/constant_folding/mod.rs b/compiler/noirc_evaluator/src/ssa/opt/constant_folding/mod.rs index 9059ee81e1a..9c527c4502a 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/constant_folding/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/constant_folding/mod.rs @@ -1667,7 +1667,7 @@ mod test { b3(): v11 = load v5 -> [Field; 4] inc_rc v11 - v14 = call poseidon2_permutation(v11, u32 4) -> [Field; 4] + v14 = call poseidon2_permutation(v11) -> [Field; 4] store v14 at v5 return b4(): diff --git a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index 740da29dece..30b520cb017 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -1050,7 +1050,9 @@ impl<'f> Context<'f> { arguments[3] = point2_x; arguments[4] = point2_y; } - + // TODO: We now use a predicate in order to disable the blackbox on the backend side + // the predicates on the inputs above will be removed once the backend is updated + arguments[5] = self.mul_by_condition(arguments[5], condition, call_stack); arguments } @@ -1058,10 +1060,12 @@ impl<'f> Context<'f> { BlackBoxFunc::MultiScalarMul => { let (elements, typ) = self.apply_predicate_to_msm_argument(arguments[0], condition, call_stack); - let instruction = Instruction::MakeArray { elements, typ }; let array = self.insert_instruction(instruction, call_stack); arguments[0] = array; + // TODO: We now use a predicate in order to disable the blackbox on the backend side + // the predicates on the inputs above will be removed once the backend is updated + arguments[2] = self.mul_by_condition(arguments[2], condition, call_stack); arguments } @@ -1095,7 +1099,9 @@ impl<'f> Context<'f> { condition, call_stack, ); - + // TODO: We now use a predicate in order to disable the blackbox on the backend side + // the predicates on the inputs above will be removed once the backend is updated + arguments[4] = self.mul_by_condition(arguments[4], condition, call_stack); arguments } BlackBoxFunc::EcdsaSecp256r1 => { @@ -1123,7 +1129,9 @@ impl<'f> Context<'f> { condition, call_stack, ); - + // TODO: We now use a predicate in order to disable the blackbox on the backend side + // the predicates on the inputs above will be removed once the backend is updated + arguments[4] = self.mul_by_condition(arguments[4], condition, call_stack); arguments } @@ -1143,15 +1151,6 @@ impl<'f> Context<'f> { BlackBoxFunc::RANGE => { unreachable!("RANGE should have been converted into `Instruction::RangeCheck`") } - - BlackBoxFunc::BigIntAdd - | BlackBoxFunc::BigIntSub - | BlackBoxFunc::BigIntMul - | BlackBoxFunc::BigIntDiv - | BlackBoxFunc::BigIntFromLeBytes - | BlackBoxFunc::BigIntToLeBytes => { - todo!("BigInt opcodes are not supported yet") - } } } diff --git a/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs b/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs index 01dd0cf47bc..b6ef2dad0ee 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs @@ -2184,7 +2184,7 @@ mod tests { v11 = load v4 -> u32 v12 = load v5 -> u1 inc_rc v10 - v15 = call poseidon2_permutation(v10, u32 4) -> [Field; 4] + v15 = call poseidon2_permutation(v10) -> [Field; 4] v16 = load v2 -> [Field; 3] v17 = load v3 -> [Field; 4] v18 = load v4 -> u32 @@ -2239,40 +2239,40 @@ mod tests { v7 = lt v4, u32 3 jmpif v7 then: b2, else: b3 b2(): - v15 = load v0 -> [Field; 3] - v16 = load v1 -> [Field; 4] - v17 = load v2 -> u32 - v18 = load v3 -> u1 - v19 = lt v4, v17 - jmpif v19 then: b4, else: b5 + v14 = load v0 -> [Field; 3] + v15 = load v1 -> [Field; 4] + v16 = load v2 -> u32 + v17 = load v3 -> u1 + v18 = lt v4, v16 + jmpif v18 then: b4, else: b5 b3(): v8 = load v0 -> [Field; 3] v9 = load v1 -> [Field; 4] v10 = load v2 -> u32 v11 = load v3 -> u1 inc_rc v9 - v14 = call poseidon2_permutation(v9, u32 4) -> [Field; 4] + v13 = call poseidon2_permutation(v9) -> [Field; 4] store v8 at v0 - store v14 at v1 + store v13 at v1 store v10 at v2 store v11 at v3 return b4(): v20 = lt v4, u32 4 constrain v20 == u1 1, "Index out of bounds" - v22 = array_get v16, index v4 -> Field + v22 = array_get v15, index v4 -> Field v23 = lt v4, u32 3 constrain v23 == u1 1, "Index out of bounds" - v24 = array_get v15, index v4 -> Field + v24 = array_get v14, index v4 -> Field v25 = add v22, v24 v26 = lt v4, u32 4 constrain v26 == u1 1, "Index out of bounds" - v27 = array_set v16, index v4, value v25 + v27 = array_set v15, index v4, value v25 v29 = unchecked_add v4, u32 1 - store v15 at v0 + store v14 at v0 store v27 at v1 - store v17 at v2 - store v18 at v3 + store v16 at v2 + store v17 at v3 jmp b5() b5(): v30 = unchecked_add v4, u32 1 diff --git a/compiler/noirc_evaluator/src/ssa/validation/mod.rs b/compiler/noirc_evaluator/src/ssa/validation/mod.rs index fb66fa91e86..a8b958db875 100644 --- a/compiler/noirc_evaluator/src/ssa/validation/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/validation/mod.rs @@ -483,15 +483,13 @@ impl<'f> Validator<'f> { } Intrinsic::SliceRemove => { // fn remove(self: [T], index: u32) -> (Self, T) {} - assert_arguments_length(arguments, 3, "SliceRemove"); + let (slice_length_type, slice_type, index_type) = + self.assert_three_arguments(arguments, "SliceRemove"); - let slice_length_type = self.function.dfg.type_of_value(arguments[0]); assert_u32(&slice_length_type, "SliceRemove self length"); - let slice_type = self.function.dfg.type_of_value(arguments[1]); let slice_element_types = assert_slice(&slice_type, "SliceRemove self slice"); - let index_type = self.function.dfg.type_of_value(arguments[2]); assert_u32(&index_type, "SliceRemove index"); let results = self.function.dfg.instruction_results(instruction); @@ -629,19 +627,14 @@ impl<'f> Validator<'f> { // iv: [u8; 16], // key: [u8; 16], // ) -> [u8; N + 16 - N % 16] {} - assert_arguments_length(arguments, 3, "aes128_encrypt"); + let (input_type, iv_type, key_type) = + self.assert_three_arguments(arguments, "aes128_encrypt"); - let input = arguments[0]; - let input_type = dfg.type_of_value(input); let input_length = assert_u8_array(&input_type, "aes128_encrypt input"); - let iv = arguments[1]; - let iv_type = dfg.type_of_value(iv); let iv_length = assert_u8_array(&iv_type, "aes128_encrypt iv"); assert_array_length(iv_length, 16, "aes128_encrypt iv"); - let key = arguments[2]; - let key_type = dfg.type_of_value(key); let key_length = assert_u8_array(&key_type, "aes128_encrypt key"); assert_array_length(key_length, 16, "aes128_encrypt key"); @@ -653,12 +646,6 @@ impl<'f> Validator<'f> { "aes128_encrypt output length mismatch" ); } - BlackBoxFunc::BigIntAdd - | BlackBoxFunc::BigIntSub - | BlackBoxFunc::BigIntMul - | BlackBoxFunc::BigIntDiv - | BlackBoxFunc::BigIntFromLeBytes - | BlackBoxFunc::BigIntToLeBytes => {} BlackBoxFunc::Blake2s | BlackBoxFunc::Blake3 => { // fn blake2s(input: [u8; N]) -> [u8; 32] // fn __blake3(input: [u8; N]) -> [u8; 32] {} @@ -675,8 +662,9 @@ impl<'f> Validator<'f> { // public_key_y: [u8; 32], // signature: [u8; 64], // message_hash: [u8; N], + // predicate: bool, // ) -> bool - assert_arguments_length(arguments, 4, "ecdsa_secp_256"); + assert_arguments_length(arguments, 5, "ecdsa_secp_256"); let public_key_x = arguments[0]; let public_key_x_type = dfg.type_of_value(public_key_x); @@ -699,13 +687,19 @@ impl<'f> Validator<'f> { let message_hash_type = dfg.type_of_value(message_hash); assert_array(&message_hash_type, "ecdsa_secp256 message_hash"); - let result_type = self.assert_one_result(instruction, "ecdsa_secp256"); + let predicate_type = dfg.type_of_value(arguments[4]); + assert_u1(&predicate_type, "ecdsa_secp256 predicate"); + + let results = dfg.instruction_results(instruction); + assert_eq!(results.len(), 1, "Expected one result"); + let result_type = dfg.type_of_value(results[0]); assert_u1(&result_type, "ecdsa_secp256 result"); } BlackBoxFunc::EmbeddedCurveAdd => { // fn embedded_curve_add_array_return( // _point1: EmbeddedCurvePoint, // _point2: EmbeddedCurvePoint, + // _predicate: bool, // ) -> [EmbeddedCurvePoint; 1] {} // // struct EmbeddedCurvePoint { @@ -713,11 +707,14 @@ impl<'f> Validator<'f> { // y: Field, // is_infinite: bool, // } - assert_arguments_length(arguments, 6, "embedded_curve_add"); + assert_arguments_length(arguments, 7, "embedded_curve_add"); assert_embedded_curve_point(arguments, 0, dfg, "embedded_curve_add _point1"); assert_embedded_curve_point(arguments, 3, dfg, "embedded_curve_add _point2"); + let predicate_type = dfg.type_of_value(arguments[6]); + assert_u1(&predicate_type, "embedded_curve_add _predicate"); + let result_type = self.assert_one_result(instruction, "embedded_curve_add"); let (result_elements, result_length) = assert_array(&result_type, "embedded_curve_add result"); @@ -738,7 +735,9 @@ impl<'f> Validator<'f> { let input_length = assert_u64_array(&input_type, "keccakf1600 input"); assert_array_length(input_length, 25, "keccakf1600 input"); - let result_type = self.assert_one_result(instruction, "keccakf1600"); + let results = dfg.instruction_results(instruction); + assert_eq!(results.len(), 1); + let result_type = dfg.type_of_value(results[0]); let result_length = assert_u64_array(&result_type, "keccakf1600 result"); assert_array_length(result_length, 25, "keccakf1600 result"); } @@ -746,9 +745,10 @@ impl<'f> Validator<'f> { // fn multi_scalar_mul_array_return( // points: [EmbeddedCurvePoint; N], // scalars: [EmbeddedCurveScalar; N], + // predicate: bool, // ) -> [EmbeddedCurvePoint; 1] {} - let (points_type, scalars_type) = - self.assert_two_arguments(arguments, "multi_scalar_mul"); + let (points_type, scalars_type, predicate_type) = + self.assert_three_arguments(arguments, "multi_scalar_mul"); let (points_elements, points_length) = assert_array(&points_type, "multi_scalar_mul points"); @@ -774,14 +774,13 @@ impl<'f> Validator<'f> { assert_field(&scalars_elements[1], "multi_scalar_mul scalars hi"); assert_eq!(points_length, scalars_length, "MSM input array lengths mismatch"); + + assert_u1(&predicate_type, "multi_scalar_mul predicate"); } BlackBoxFunc::Poseidon2Permutation => { - // fn poseidon2_permutation(_input: [Field; N], _state_length: u32) -> [Field; N] {} - let (input_type, state_length_type) = - self.assert_two_arguments(arguments, "poseidon2_permutation"); - + // fn poseidon2_permutation(_input: [Field; N]) -> [Field; N] {} + let input_type = self.assert_one_argument(arguments, "poseidon2_permutation"); let input_length = assert_field_array(&input_type, "poseidon2_permutation _input"); - assert_u32(&state_length_type, "poseidon2_permutation _state_length"); let result_type = self.assert_one_result(instruction, "poseidon2_permutation"); let result_length = @@ -860,6 +859,20 @@ impl<'f> Validator<'f> { ) } + fn assert_three_arguments( + &self, + arguments: &[ValueId], + object: &'static str, + ) -> (Type, Type, Type) { + assert_arguments_length(arguments, 3, object); + + ( + self.function.dfg.type_of_value(arguments[0]), + self.function.dfg.type_of_value(arguments[1]), + self.function.dfg.type_of_value(arguments[2]), + ) + } + fn assert_no_results(&self, instruction: InstructionId, object: &'static str) { let results = self.function.dfg.instruction_results(instruction); assert_eq!(results.len(), 0, "Expected zero result for {object}",); @@ -1571,9 +1584,9 @@ mod tests { fn msm_has_incorrect_type() { let src = " acir(inline) fn main f0 { - b0(v0: [(Field, Field, Field); 3], v1: [(Field, Field); 3]): - v2 = call multi_scalar_mul(v0, v1) -> [(Field, Field, u1); 1] - return v2 + b0(v0: [(Field, Field, Field); 3], v1: [(Field, Field); 3], v2: u1): + v3 = call multi_scalar_mul(v0, v1, v2) -> [(Field, Field, u1); 1] + return v3 } "; let _ = Ssa::from_str(src).unwrap(); diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter.rs index 68ab0158cac..2339294d1a6 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter.rs @@ -2,7 +2,6 @@ use std::collections::VecDeque; use std::{collections::hash_map::Entry, rc::Rc}; use acvm::AcirField; -use acvm::blackbox_solver::BigIntSolverWithId; use im::Vector; use iter_extended::try_vecmap; use noirc_errors::Location; @@ -67,9 +66,6 @@ pub struct Interpreter<'local, 'interner> { /// multiple times. Without this map, when one of these inner functions exits we would /// unbind the generic completely instead of resetting it to its previous binding. bound_generics: Vec>, - - /// Stateful bigint calculator. - bigint_solver: BigIntSolverWithId, } #[allow(unused)] @@ -80,15 +76,7 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { current_function: Option, ) -> Self { let pedantic_solving = elaborator.pedantic_solving(); - let bigint_solver = BigIntSolverWithId::with_pedantic_solving(pedantic_solving); - Self { - elaborator, - crate_id, - current_function, - bound_generics: Vec::new(), - in_loop: false, - bigint_solver, - } + Self { elaborator, crate_id, current_function, bound_generics: Vec::new(), in_loop: false } } pub(crate) fn call_function( diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter/foreign.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter/foreign.rs index 10b50255bb0..6c9089cb121 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter/foreign.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter/foreign.rs @@ -1,7 +1,6 @@ use acvm::{ - AcirField, BlackBoxResolutionError, FieldElement, - acir::BlackBoxFunc, - blackbox_solver::{BigIntSolverWithId, BlackBoxFunctionSolver}, + AcirField, BlackBoxResolutionError, FieldElement, acir::BlackBoxFunc, + blackbox_solver::BlackBoxFunctionSolver, }; use bn254_blackbox_solver::Bn254BlackBoxSolver; // Currently locked to only bn254! use im::{Vector, vector}; @@ -37,7 +36,6 @@ impl Interpreter<'_, '_> { ) -> IResult { call_foreign( self.elaborator.interner, - &mut self.bigint_solver, name, arguments, return_type, @@ -50,25 +48,14 @@ impl Interpreter<'_, '_> { // Similar to `evaluate_black_box` in `brillig_vm`. fn call_foreign( interner: &mut NodeInterner, - bigint_solver: &mut BigIntSolverWithId, name: &str, args: Vec<(Value, Location)>, return_type: Type, location: Location, pedantic_solving: bool, ) -> IResult { - use BlackBoxFunc::*; - match name { "aes128_encrypt" => aes128_encrypt(interner, args, location), - "bigint_from_le_bytes" => { - bigint_from_le_bytes(interner, bigint_solver, args, return_type, location) - } - "bigint_to_le_bytes" => bigint_to_le_bytes(bigint_solver, args, location), - "bigint_add" => bigint_op(bigint_solver, BigIntAdd, args, return_type, location), - "bigint_sub" => bigint_op(bigint_solver, BigIntSub, args, return_type, location), - "bigint_mul" => bigint_op(bigint_solver, BigIntMul, args, return_type, location), - "bigint_div" => bigint_op(bigint_solver, BigIntDiv, args, return_type, location), "blake2s" => blake_hash(interner, args, location, acvm::blackbox_solver::blake2s), "blake3" => blake_hash(interner, args, location, acvm::blackbox_solver::blake3), // cSpell:disable-next-line @@ -150,71 +137,6 @@ fn apply_range_constraint(arguments: Vec<(Value, Location)>, location: Location) } } -/// `fn from_le_bytes(bytes: [u8], modulus: [u8]) -> BigInt` -/// -/// Returns the ID of the new bigint allocated by the solver. -fn bigint_from_le_bytes( - interner: &mut NodeInterner, - solver: &mut BigIntSolverWithId, - arguments: Vec<(Value, Location)>, - return_type: Type, - location: Location, -) -> IResult { - let (bytes, modulus) = check_two_arguments(arguments, location)?; - - let (bytes, _) = get_slice_map(interner, bytes, get_u8)?; - let (modulus, _) = get_slice_map(interner, modulus, get_u8)?; - - let id = solver - .bigint_from_bytes(&bytes, &modulus) - .map_err(|e| InterpreterError::BlackBoxError(e, location))?; - - Ok(to_bigint(id, return_type)) -} - -/// `fn to_le_bytes(self) -> [u8; 32]` -/// -/// Take the ID of a bigint and returned its content. -fn bigint_to_le_bytes( - solver: &mut BigIntSolverWithId, - arguments: Vec<(Value, Location)>, - location: Location, -) -> IResult { - let int = check_one_argument(arguments, location)?; - let id = get_bigint_id(int)?; - - let mut bytes = - solver.bigint_to_bytes(id).map_err(|e| InterpreterError::BlackBoxError(e, location))?; - - assert!(bytes.len() <= 32); - bytes.resize(32, 0); - - Ok(to_byte_array(&bytes)) -} - -/// `fn bigint_add(self, other: BigInt) -> BigInt` -/// -/// Takes two previous allocated IDs, gets the values from the solver, -/// stores the result of the operation, returns the new ID. -fn bigint_op( - solver: &mut BigIntSolverWithId, - func: BlackBoxFunc, - arguments: Vec<(Value, Location)>, - return_type: Type, - location: Location, -) -> IResult { - let (lhs, rhs) = check_two_arguments(arguments, location)?; - - let lhs = get_bigint_id(lhs)?; - let rhs = get_bigint_id(rhs)?; - - let id = solver - .bigint_op(lhs, rhs, func) - .map_err(|e| InterpreterError::BlackBoxError(e, location))?; - - Ok(to_bigint(id, return_type)) -} - /// Run one of the Blake hash functions. /// ```text /// pub fn blake2s(input: [u8; N]) -> [u8; 32] @@ -250,7 +172,8 @@ fn ecdsa_secp256_verify( location: Location, f: impl Fn(&[u8], &[u8; 32], &[u8; 32], &[u8; 64]) -> Result, ) -> IResult { - let [pub_key_x, pub_key_y, sig, msg_hash] = check_arguments(arguments, location)?; + let [pub_key_x, pub_key_y, sig, msg_hash, predicate] = check_arguments(arguments, location)?; + assert_eq!(predicate.0, Value::Bool(true), "verify_signature predicate should be true"); let (pub_key_x, _) = get_fixed_array_map(interner, pub_key_x, get_u8)?; let (pub_key_y, _) = get_fixed_array_map(interner, pub_key_y, get_u8)?; @@ -281,7 +204,8 @@ fn embedded_curve_add( location: Location, pedantic_solving: bool, ) -> IResult { - let (point1, point2) = check_two_arguments(arguments, location)?; + let (point1, point2, predicate) = check_three_arguments(arguments, location)?; + assert_eq!(predicate.0, Value::Bool(true), "ec_add predicate should be true"); let embedded_curve_point_typ = point1.0.get_type().into_owned(); @@ -311,7 +235,8 @@ fn multi_scalar_mul( location: Location, pedantic_solving: bool, ) -> IResult { - let (points, scalars) = check_two_arguments(arguments, location)?; + let (points, scalars, predicate) = check_three_arguments(arguments, location)?; + assert_eq!(predicate.0, Value::Bool(true), "verify_signature predicate should be true"); let (points, _) = get_array_map(interner, points, get_embedded_curve_point)?; let (scalars, _) = get_array_map(interner, scalars, get_embedded_curve_scalar)?; @@ -355,14 +280,13 @@ fn poseidon2_permutation( location: Location, pedantic_solving: bool, ) -> IResult { - let (input, state_length) = check_two_arguments(arguments, location)?; + let input = check_one_argument(arguments, location)?; let (input, typ) = get_array_map(interner, input, get_field)?; let input = vecmap(input, SignedField::to_field_element); - let state_length = get_u32(state_length)?; let fields = Bn254BlackBoxSolver(pedantic_solving) - .poseidon2_permutation(&input, state_length) + .poseidon2_permutation(&input) .map_err(|error| InterpreterError::BlackBoxError(error, location))?; let array = fields.into_iter().map(|f| Value::Field(SignedField::positive(f))).collect(); @@ -403,17 +327,6 @@ fn sha256_compression( Ok(Value::Array(state, typ)) } -/// Decode a `BigInt` struct. -/// -/// Returns the ID of the value in the solver. -fn get_bigint_id((value, location): (Value, Location)) -> IResult { - let (fields, typ) = get_struct_fields("BigInt", (value, location))?; - let p = get_struct_field("pointer", &fields, &typ, location, get_u32)?; - let m = get_struct_field("modulus", &fields, &typ, location, get_u32)?; - assert_eq!(p, m, "`pointer` and `modulus` are expected to be the same"); - Ok(p) -} - /// Decode an `EmbeddedCurvePoint` struct. /// /// Returns `(x, y, is_infinite)`. @@ -439,10 +352,6 @@ fn get_embedded_curve_scalar( Ok((lo.to_field_element(), hi.to_field_element())) } -fn to_bigint(id: u32, typ: Type) -> Value { - to_struct([("pointer", Value::U32(id)), ("modulus", Value::U32(id))], typ) -} - fn to_embedded_curve_point( x: FieldElement, y: FieldElement, @@ -491,7 +400,6 @@ mod tests { let pedantic_solving = true; match call_foreign( interpreter.elaborator.interner, - &mut interpreter.bigint_solver, name, Vec::new(), Type::Unit, diff --git a/examples/browser/package.json b/examples/browser/package.json index 56226105348..6bace525e2d 100644 --- a/examples/browser/package.json +++ b/examples/browser/package.json @@ -8,7 +8,7 @@ "test": "yarn build && playwright test browser.test.ts" }, "dependencies": { - "@aztec/bb.js": "1.2.0", + "@aztec/bb.js": "v3.0.0-nightly.20250916", "@noir-lang/noir_js": "workspace:*" }, "devDependencies": { diff --git a/noir_stdlib/src/ecdsa_secp256k1.nr b/noir_stdlib/src/ecdsa_secp256k1.nr index 296ceeb6f96..d19f7ba6322 100644 --- a/noir_stdlib/src/ecdsa_secp256k1.nr +++ b/noir_stdlib/src/ecdsa_secp256k1.nr @@ -1,4 +1,3 @@ -#[foreign(ecdsa_secp256k1)] // docs:start:ecdsa_secp256k1 /// Verifies a ECDSA signature over the secp256k1 curve. /// - inputs: @@ -22,4 +21,15 @@ pub fn verify_signature( message_hash: [u8; N], ) -> bool // docs:end:ecdsa_secp256k1 -{} +{ + _verify_signature(public_key_x, public_key_y, signature, message_hash, true) +} + +#[foreign(ecdsa_secp256k1)] +pub fn _verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N], + predicate: bool, +) -> bool {} diff --git a/noir_stdlib/src/ecdsa_secp256r1.nr b/noir_stdlib/src/ecdsa_secp256r1.nr index 95f9ebbe128..fc130a03b37 100644 --- a/noir_stdlib/src/ecdsa_secp256r1.nr +++ b/noir_stdlib/src/ecdsa_secp256r1.nr @@ -1,4 +1,3 @@ -#[foreign(ecdsa_secp256r1)] // docs:start:ecdsa_secp256r1 pub fn verify_signature( public_key_x: [u8; 32], @@ -7,4 +6,15 @@ pub fn verify_signature( message_hash: [u8; N], ) -> bool // docs:end:ecdsa_secp256r1 -{} +{ + _verify_signature(public_key_x, public_key_y, signature, message_hash, true) +} + +#[foreign(ecdsa_secp256r1)] +pub fn _verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N], + predicate: bool, +) -> bool {} diff --git a/noir_stdlib/src/embedded_curve_ops.nr b/noir_stdlib/src/embedded_curve_ops.nr index 685ef67192c..7f852816a98 100644 --- a/noir_stdlib/src/embedded_curve_ops.nr +++ b/noir_stdlib/src/embedded_curve_ops.nr @@ -142,13 +142,14 @@ pub fn multi_scalar_mul( ) -> EmbeddedCurvePoint // docs:end:multi_scalar_mul { - multi_scalar_mul_array_return(points, scalars)[0] + multi_scalar_mul_array_return(points, scalars, true)[0] } #[foreign(multi_scalar_mul)] pub(crate) fn multi_scalar_mul_array_return( points: [EmbeddedCurvePoint; N], scalars: [EmbeddedCurveScalar; N], + predicate: bool, ) -> [EmbeddedCurvePoint; 1] {} // docs:start:fixed_base_scalar_mul @@ -234,6 +235,7 @@ pub fn embedded_curve_add( fn embedded_curve_add_array_return( _point1: EmbeddedCurvePoint, _point2: EmbeddedCurvePoint, + _predicate: bool, ) -> [EmbeddedCurvePoint; 1] {} /// This function assumes that: @@ -264,5 +266,5 @@ pub fn embedded_curve_add_unsafe( point1: EmbeddedCurvePoint, point2: EmbeddedCurvePoint, ) -> EmbeddedCurvePoint { - embedded_curve_add_array_return(point1, point2)[0] + embedded_curve_add_array_return(point1, point2, true)[0] } diff --git a/noir_stdlib/src/hash/mod.nr b/noir_stdlib/src/hash/mod.nr index 0f14450617a..0b5d9970092 100644 --- a/noir_stdlib/src/hash/mod.nr +++ b/noir_stdlib/src/hash/mod.nr @@ -92,7 +92,7 @@ pub fn pedersen_hash_with_separator(input: [Field; N], separator: u3 let length_generator: [EmbeddedCurvePoint; 1] = derive_generators("pedersen_hash_length".as_bytes(), 0); generators[N] = length_generator[0]; - multi_scalar_mul_array_return(generators, scalars)[0].x + multi_scalar_mul_array_return(generators, scalars, true)[0].x } #[field(bn254)] @@ -125,8 +125,13 @@ fn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar { EmbeddedCurveScalar { lo: xlo, hi: xhi } } +pub fn poseidon2_permutation(input: [Field; N], state_len: u32) -> [Field; N] { + assert_eq(input.len(), state_len); + poseidon2_permutation_internal(input) +} + #[foreign(poseidon2_permutation)] -pub fn poseidon2_permutation(_input: [Field; N], _state_length: u32) -> [Field; N] {} +fn poseidon2_permutation_internal(input: [Field; N]) -> [Field; N] {} // Generic hashing support. // Partially ported and impacted by rust. diff --git a/noir_stdlib/src/hash/poseidon2.nr b/noir_stdlib/src/hash/poseidon2.nr index 4da78b1d96a..c5b57ab519f 100644 --- a/noir_stdlib/src/hash/poseidon2.nr +++ b/noir_stdlib/src/hash/poseidon2.nr @@ -32,7 +32,7 @@ impl Poseidon2 { self.state[i] += self.cache[i]; } } - self.state = crate::hash::poseidon2_permutation(self.state, 4); + self.state = crate::hash::poseidon2_permutation_internal(self.state); } fn absorb(&mut self, input: Field) { diff --git a/scripts/install_bb.sh b/scripts/install_bb.sh index 16fa271b07a..3a4261cf11e 100755 --- a/scripts/install_bb.sh +++ b/scripts/install_bb.sh @@ -1,11 +1,11 @@ #!/bin/bash -VERSION="1.2.0" +VERSION="3.0.0-nightly.20250916" BBUP_PATH=~/.bb/bbup if ! [ -f $BBUP_PATH ]; then - curl -L https://bbup.aztec.network | bash + curl -L https://raw.githubusercontent.com/AztecProtocol/aztec-packages/refs/heads/next/barretenberg/bbup/install | bash fi $BBUP_PATH -v $VERSION diff --git a/tooling/debugger/src/context.rs b/tooling/debugger/src/context.rs index ac881acebf7..e08cfb5833e 100644 --- a/tooling/debugger/src/context.rs +++ b/tooling/debugger/src/context.rs @@ -1106,6 +1106,7 @@ mod tests { let w_x = Witness(1); let brillig_bytecode = BrilligBytecode { + function_name: "clear_mock".into(), bytecode: vec![ BrilligOpcode::Const { destination: MemoryAddress::direct(1), @@ -1263,6 +1264,7 @@ mod tests { // This Brillig block is equivalent to: z = x + y let brillig_bytecode = BrilligBytecode { + function_name: "add".into(), bytecode: vec![ BrilligOpcode::Const { destination: MemoryAddress::direct(0), @@ -1380,9 +1382,12 @@ mod tests { #[test] fn test_address_debug_location_mapping() { let solver = StubbedBlackBoxSolver::default(); - let brillig_one = - BrilligBytecode { bytecode: vec![BrilligOpcode::Return, BrilligOpcode::Return] }; + let brillig_one = BrilligBytecode { + function_name: "one".to_string(), + bytecode: vec![BrilligOpcode::Return, BrilligOpcode::Return], + }; let brillig_two = BrilligBytecode { + function_name: "two".to_string(), bytecode: vec![BrilligOpcode::Return, BrilligOpcode::Return, BrilligOpcode::Return], }; diff --git a/tooling/greybox_fuzzer/src/coverage.rs b/tooling/greybox_fuzzer/src/coverage.rs index d5951b67437..b4e24526437 100644 --- a/tooling/greybox_fuzzer/src/coverage.rs +++ b/tooling/greybox_fuzzer/src/coverage.rs @@ -640,8 +640,7 @@ pub fn analyze_brillig_program_before_fuzzing( for (opcode_index, opcode) in fuzzed_brillig_function.bytecode.iter().enumerate() { match opcode { // Conditional branching - &BrilligOpcode::JumpIf { location, .. } - | &BrilligOpcode::JumpIfNot { location, .. } => { + &BrilligOpcode::JumpIf { location, .. } => { feature_to_index_map.insert((opcode_index, location), total_features); feature_to_index_map.insert((opcode_index, opcode_index + 1), total_features + 1); coverage_items.push(BrilligCoverageItemRange::Branch(BranchCoverageRange { diff --git a/tooling/greybox_fuzzer/src/dictionary.rs b/tooling/greybox_fuzzer/src/dictionary.rs index 824527ed4c5..e80be8d7521 100644 --- a/tooling/greybox_fuzzer/src/dictionary.rs +++ b/tooling/greybox_fuzzer/src/dictionary.rs @@ -11,7 +11,7 @@ use acvm::{ circuit::{ Circuit, Opcode, Program, brillig::{BrilligBytecode, BrilligInputs}, - opcodes::{BlackBoxFuncCall, ConstantOrWitnessEnum}, + opcodes::{BlackBoxFuncCall, FunctionInput}, }, native_types::Expression, }, @@ -61,9 +61,9 @@ fn build_dictionary_from_circuit(circuit: &Circuit) -> HashSet< for opcode in &circuit.opcodes { match opcode { - Opcode::AssertZero(expr) - | Opcode::Call { predicate: Some(expr), .. } - | Opcode::MemoryOp { predicate: Some(expr), .. } => insert_expr(&mut constants, expr), + Opcode::AssertZero(expr) | Opcode::Call { predicate: Some(expr), .. } => { + insert_expr(&mut constants, expr); + } Opcode::MemoryInit { init, .. } => insert_array_len(&mut constants, init), @@ -83,18 +83,18 @@ fn build_dictionary_from_circuit(circuit: &Circuit) -> HashSet< } } - Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { input }) - if matches!(input.input(), ConstantOrWitnessEnum::Constant(..)) => + Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { input, num_bits }) + if matches!(input, FunctionInput::Constant(..)) => { - match input.input() { - ConstantOrWitnessEnum::Constant(c) => { - let field = 1u128.wrapping_shl(input.num_bits()); + match input { + FunctionInput::Constant(c) => { + let field = 1u128.wrapping_shl(*num_bits); constants.insert(F::from(field)); constants.insert(F::from(field - 1)); - constants.insert(c); + constants.insert(*c); } _ => { - let field = 1u128.wrapping_shl(input.num_bits()); + let field = 1u128.wrapping_shl(*num_bits); constants.insert(F::from(field)); constants.insert(F::from(field - 1)); } diff --git a/tooling/lsp/src/solver.rs b/tooling/lsp/src/solver.rs index df5c8eeb44f..819d3f558d1 100644 --- a/tooling/lsp/src/solver.rs +++ b/tooling/lsp/src/solver.rs @@ -40,8 +40,7 @@ impl BlackBoxFunctionSolver for WrapperSolver { fn poseidon2_permutation( &self, inputs: &[acvm::FieldElement], - len: u32, ) -> Result, acvm::BlackBoxResolutionError> { - self.0.poseidon2_permutation(inputs, len) + self.0.poseidon2_permutation(inputs) } } diff --git a/tooling/nargo/Cargo.toml b/tooling/nargo/Cargo.toml index 111b883c278..f147e07133c 100644 --- a/tooling/nargo/Cargo.toml +++ b/tooling/nargo/Cargo.toml @@ -38,6 +38,10 @@ rand = { workspace = true, optional = true } [dev-dependencies] jsonrpsee = { workspace = true, features = ["server"] } +serde_json.workspace = true +proptest.workspace = true +proptest-derive.workspace = true +num-bigint.workspace = true [features] default = [] diff --git a/tooling/nargo/src/foreign_calls/rpc.rs b/tooling/nargo/src/foreign_calls/rpc.rs index 82f27ace792..20248d3c168 100644 --- a/tooling/nargo/src/foreign_calls/rpc.rs +++ b/tooling/nargo/src/foreign_calls/rpc.rs @@ -1,6 +1,10 @@ use std::path::PathBuf; -use acvm::{AcirField, acir::brillig::ForeignCallResult, pwg::ForeignCallWaitInfo}; +use acvm::{ + AcirField, + acir::brillig::{ForeignCallParam, ForeignCallResult}, + pwg::ForeignCallWaitInfo, +}; use jsonrpsee::{ core::client::ClientT, http_client::{HttpClient, HttpClientBuilder}, @@ -54,6 +58,79 @@ struct ResolveForeignCallRequest { package_name: Option, } +#[derive(Eq, PartialEq, Debug, Clone)] +#[cfg_attr(test, derive(proptest_derive::Arbitrary))] +struct JSONSerializableFieldElement(F); + +impl JSONSerializableFieldElement { + fn new(value: F) -> Self { + JSONSerializableFieldElement(value) + } + + fn into_inner(self) -> F { + self.0 + } +} + +impl Serialize for JSONSerializableFieldElement { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.0.to_hex().serialize(serializer) + } +} + +impl<'de, F: AcirField> Deserialize<'de> for JSONSerializableFieldElement { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s: std::borrow::Cow<'de, str> = Deserialize::deserialize(deserializer)?; + match F::from_hex(&s) { + Some(value) => Ok(Self(value)), + None => Err(serde::de::Error::custom(format!("Invalid hex for FieldElement: {s}",))), + } + } +} + +fn prepare_foreign_call( + foreign_call: ForeignCallWaitInfo, +) -> ForeignCallWaitInfo> { + ForeignCallWaitInfo { + function: foreign_call.function, + inputs: foreign_call + .inputs + .into_iter() + .map(|param| match param { + ForeignCallParam::Single(value) => { + ForeignCallParam::Single(JSONSerializableFieldElement::new(value)) + } + ForeignCallParam::Array(values) => ForeignCallParam::Array( + values.into_iter().map(JSONSerializableFieldElement::new).collect(), + ), + }) + .collect(), + } +} + +fn receive_foreign_call_result( + foreign_call_result: ForeignCallResult>, +) -> ForeignCallResult { + ForeignCallResult { + values: foreign_call_result + .values + .into_iter() + .map(|param| match param { + ForeignCallParam::Single(value) => ForeignCallParam::Single(value.into_inner()), + ForeignCallParam::Array(values) => ForeignCallParam::Array( + values.into_iter().map(|val| val.into_inner()).collect(), + ), + }) + .collect(), + } +} + type ResolveForeignCallResult = Result, ForeignCallError>; impl RPCForeignCallExecutor { @@ -90,9 +167,11 @@ impl RPCForeignCallExecutor { where F: AcirField + Serialize + for<'a> Deserialize<'a>, { + let foreign_call = prepare_foreign_call(foreign_call.clone()); + let params = ResolveForeignCallRequest { session_id: self.id, - function_call: foreign_call.clone(), + function_call: foreign_call, root_path: self .root_path .clone() @@ -101,9 +180,14 @@ impl RPCForeignCallExecutor { package_name: self.package_name.clone().or(Some(String::new())), }; let encoded_params = rpc_params!(params); - self.runtime.block_on(async { + let response: Result< + ForeignCallResult>, + jsonrpsee::core::ClientError, + > = self.runtime.block_on(async { self.external_resolver.request("resolve_foreign_call", encoded_params).await - }) + }); + + response.map(receive_foreign_call_result) } } @@ -151,31 +235,64 @@ mod serialization_tests { AcirField, FieldElement, acir::brillig::ForeignCallParam, brillig_vm::brillig::ForeignCallResult, }; + use proptest::prelude::*; + + use super::JSONSerializableFieldElement; #[test] fn deserializes_json_as_expected() { - let raw_responses: [(&str, Vec>); 3] = [ + let raw_responses: [( + &str, + Vec>>, + ); 3] = [ ("[]", Vec::new()), ( "[\"0x0000000000000000000000000000000000000000000000000000000000000001\"]", - vec![ForeignCallParam::Single(FieldElement::one())], + vec![ForeignCallParam::Single(JSONSerializableFieldElement::new( + FieldElement::one(), + ))], ), ("[[]]", vec![ForeignCallParam::Array(Vec::new())]), ]; for (raw_response, expected) in raw_responses { - let decoded_response: ForeignCallResult = + let decoded_response: ForeignCallResult> = serde_json::from_str(&format!("{{ \"values\": {raw_response} }}")).unwrap(); assert_eq!(decoded_response, ForeignCallResult { values: expected }); } } + + acvm::acir::acir_field::field_wrapper!(TestField, FieldElement); + + impl Arbitrary for TestField { + type Parameters = (); + type Strategy = BoxedStrategy; + + fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { + any::().prop_map(|v| Self(FieldElement::from(v))).boxed() + } + } + + proptest! { + /// We want to ensure that the serialization and deserialization of arrays of fields works correctly + /// with `JSONSerializableFieldElement` as JSON serialization on `FieldElement` confuses empty arrays with a field element. + #[test] + fn arrays_of_fields_serialization_roundtrip(param: Vec>) { + let serialized = serde_json::to_string(¶m).unwrap(); + let deserialized: Vec> = serde_json::from_str(&serialized).unwrap(); + + prop_assert_eq!(param, deserialized); + } + + + } } #[cfg(test)] mod server_tests { use acvm::{ - FieldElement, acir::brillig::ForeignCallParam, brillig_vm::brillig::ForeignCallResult, - pwg::ForeignCallWaitInfo, + AcirField, FieldElement, acir::brillig::ForeignCallParam, + brillig_vm::brillig::ForeignCallResult, pwg::ForeignCallWaitInfo, }; use jsonrpsee::proc_macros::rpc; use jsonrpsee::server::Server; @@ -183,17 +300,62 @@ mod server_tests { use tokio::sync::{mpsc, oneshot}; use super::{ - ForeignCallExecutor, RPCForeignCallExecutor, ResolveForeignCallRequest, - ResolveForeignCallResult, + ForeignCallExecutor, JSONSerializableFieldElement, RPCForeignCallExecutor, + ResolveForeignCallRequest, ResolveForeignCallResult, }; + /// Convert the foreign call request from the RPC client to the internal format. + /// + /// This is used to convert the request from the JSON RPC client to the format expected by + /// the `ForeignCallExecutor`. + fn receive_foreign_call( + foreign_call: ForeignCallWaitInfo>, + ) -> ForeignCallWaitInfo { + ForeignCallWaitInfo { + function: foreign_call.function, + inputs: foreign_call + .inputs + .into_iter() + .map(|param| match param { + ForeignCallParam::Single(value) => ForeignCallParam::Single(value.into_inner()), + ForeignCallParam::Array(values) => ForeignCallParam::Array( + values.into_iter().map(|val| val.into_inner()).collect(), + ), + }) + .collect(), + } + } + + /// Convert the foreign call result from the internal format to the JSON RPC client format. + /// + /// This is used to convert the response from the `ForeignCallExecutor` to the format expected by + /// the JSON RPC client. + fn prepare_foreign_call_result( + foreign_call_result: ForeignCallResult, + ) -> ForeignCallResult> { + ForeignCallResult { + values: foreign_call_result + .values + .into_iter() + .map(|param| match param { + ForeignCallParam::Single(value) => { + ForeignCallParam::Single(JSONSerializableFieldElement::new(value)) + } + ForeignCallParam::Array(values) => ForeignCallParam::Array( + values.into_iter().map(JSONSerializableFieldElement::new).collect(), + ), + }) + .collect(), + } + } + #[rpc(server)] trait OracleResolver { #[method(name = "resolve_foreign_call")] fn resolve_foreign_call( &self, - req: ResolveForeignCallRequest, - ) -> Result, ErrorObjectOwned>; + req: ResolveForeignCallRequest>, + ) -> Result>, ErrorObjectOwned>; } struct OracleResolverImpl; @@ -217,15 +379,17 @@ mod server_tests { impl OracleResolverServer for OracleResolverImpl { fn resolve_foreign_call( &self, - req: ResolveForeignCallRequest, - ) -> Result, ErrorObjectOwned> { - let response = match req.function_call.function.as_str() { - "sum" => self.sum(req.function_call.inputs[0].clone()), - "echo" => self.echo(req.function_call.inputs[0].clone()), + req: ResolveForeignCallRequest>, + ) -> Result>, ErrorObjectOwned> + { + let foreign_call = receive_foreign_call(req.function_call); + let response = match foreign_call.function.as_str() { + "sum" => self.sum(foreign_call.inputs[0].clone()), + "echo" => self.echo(foreign_call.inputs[0].clone()), "id" => FieldElement::from(u128::from(req.session_id)).into(), _ => panic!("unexpected foreign call"), }; - Ok(response) + Ok(prepare_foreign_call_result(response)) } } diff --git a/tooling/nargo/src/ops/check.rs b/tooling/nargo/src/ops/check.rs index 466e66c06d9..7cef18faac9 100644 --- a/tooling/nargo/src/ops/check.rs +++ b/tooling/nargo/src/ops/check.rs @@ -14,7 +14,7 @@ pub fn check_program(compiled_program: &CompiledProgram) -> Result<(), ErrorsAnd let call_stack = compiled_program.debug[i].location_tree.get_call_stack(*call_stack); CustomDiagnostic::from_message( - &format!("Circuit \"{}\" is not solvable", compiled_program.names[i]), + &format!("Circuit \"{}\" is not solvable", circuit.function_name), call_stack[0].file, ) .with_call_stack(call_stack) @@ -22,7 +22,7 @@ pub fn check_program(compiled_program: &CompiledProgram) -> Result<(), ErrorsAnd CustomDiagnostic::from_message( &format!( "Circuit \"{}\" is not solvable for opcode \"{}\"", - compiled_program.names[i], opcode + circuit.function_name, opcode ), fm::FileId::dummy(), ) diff --git a/tooling/nargo_cli/src/cli/compile_cmd.rs b/tooling/nargo_cli/src/cli/compile_cmd.rs index 8b39208bece..01416d8f4fd 100644 --- a/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -239,16 +239,10 @@ fn compile_programs( // If the compiled program is the same as the cached one, we don't apply transformations again, unless the target width has changed. // The transformations might not be idempotent, which would risk creating witnesses that don't work with earlier versions, // based on which we might have generated a verifier already. - if cached_hash == Some(rustc_hash::FxBuildHasher.hash_one(&program)) { - let width_matches = program - .program - .functions - .iter() - .all(|circuit| circuit.expression_width == target_width); - - if width_matches { - return Ok(((), warnings)); - } + if cached_hash == Some(rustc_hash::FxBuildHasher.hash_one(&program)) + && program.expression_width == target_width + { + return Ok(((), warnings)); } // Run ACVM optimizations and set the target width. let program = nargo::ops::transform_program(program, target_width); diff --git a/tooling/nargo_cli/tests/snapshots/compile_failure/option_expect_bad_input/execute__tests__stderr.snap b/tooling/nargo_cli/tests/snapshots/compile_failure/option_expect_bad_input/execute__tests__stderr.snap index 6f41c3e732c..9dc9fde6082 100644 --- a/tooling/nargo_cli/tests/snapshots/compile_failure/option_expect_bad_input/execute__tests__stderr.snap +++ b/tooling/nargo_cli/tests/snapshots/compile_failure/option_expect_bad_input/execute__tests__stderr.snap @@ -13,14 +13,14 @@ error: Type annotation needed ┌─ src/main.nr:5:12 │ 5 │ assert(some.expect("Should have the value {inner_value}") == 3); - │ ----------- Could not determine the type of the generic argument `MessageTypes` declared on the function `expect` + │ ----------- Could not determine the value of the generic argument `N` declared on the function `expect` │ error: Type annotation needed ┌─ src/main.nr:5:12 │ 5 │ assert(some.expect("Should have the value {inner_value}") == 3); - │ ----------- Could not determine the value of the generic argument `N` declared on the function `expect` + │ ----------- Could not determine the type of the generic argument `MessageTypes` declared on the function `expect` │ Aborting due to 3 previous errors diff --git a/tooling/nargo_cli/tests/snapshots/compile_success_empty/arithmetic_generics/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/compile_success_empty/arithmetic_generics/execute__tests__expanded.snap index 43071ebc59c..7b0546458da 100644 --- a/tooling/nargo_cli/tests/snapshots/compile_success_empty/arithmetic_generics/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/compile_success_empty/arithmetic_generics/execute__tests__expanded.snap @@ -24,8 +24,8 @@ fn split_first(array: [T; N]) -> (T, [T; N - 1]) { fn push(array: [Field; N], element: Field) -> [Field; N + 1] { let mut result: [Field; N + 1] = std::mem::zeroed(); { - let i_4383: u32 = array.len(); - result[i_4383] = element; + let i_4402: u32 = array.len(); + result[i_4402] = element; }; for i in 0_u32..array.len() { result[i] = array[i]; diff --git a/tooling/nargo_cli/tests/snapshots/compile_success_empty/assign_mutation_in_lvalue/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/compile_success_empty/assign_mutation_in_lvalue/execute__tests__expanded.snap index f1854826f49..e9d80e17ac5 100644 --- a/tooling/nargo_cli/tests/snapshots/compile_success_empty/assign_mutation_in_lvalue/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/compile_success_empty/assign_mutation_in_lvalue/execute__tests__expanded.snap @@ -10,11 +10,11 @@ fn main() { fn bug() { let mut a: ([Field; 2], Field) = ([1_Field, 2_Field], 3_Field); { - let i_4352: u32 = { + let i_4371: u32 = { a = ([4_Field, 5_Field], 6_Field); 1_u32 }; - a.0[i_4352] = 7_Field; + a.0[i_4371] = 7_Field; }; assert(a == ([4_Field, 7_Field], 6_Field)); } diff --git a/tooling/nargo_cli/tests/snapshots/compile_success_empty/numeric_generics/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/compile_success_empty/numeric_generics/execute__tests__expanded.snap index 50e8feebfb5..9a6cdff247f 100644 --- a/tooling/nargo_cli/tests/snapshots/compile_success_empty/numeric_generics/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/compile_success_empty/numeric_generics/execute__tests__expanded.snap @@ -27,8 +27,8 @@ impl MyStruct { fn insert(mut self, index: Field, elem: Field) -> Self { assert((index as u64) < (S as u64)); { - let i_4366: u32 = index as u32; - self.data[i_4366] = elem; + let i_4385: u32 = index as u32; + self.data[i_4385] = elem; }; self } diff --git a/tooling/nargo_cli/tests/snapshots/compile_success_empty/numeric_generics_explicit/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/compile_success_empty/numeric_generics_explicit/execute__tests__expanded.snap index 341c77b5df0..a8481902d80 100644 --- a/tooling/nargo_cli/tests/snapshots/compile_success_empty/numeric_generics_explicit/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/compile_success_empty/numeric_generics_explicit/execute__tests__expanded.snap @@ -36,8 +36,8 @@ impl MyStruct { fn insert(mut self, index: Field, elem: Field) -> Self { assert((index as u32) < S); { - let i_4384: u32 = index as u32; - self.data[i_4384] = elem; + let i_4403: u32 = index as u32; + self.data[i_4403] = elem; }; self } diff --git a/tooling/nargo_cli/tests/snapshots/compile_success_empty/regression_bignum/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/compile_success_empty/regression_bignum/execute__tests__expanded.snap index 27e1def0add..1fc3f3db5ce 100644 --- a/tooling/nargo_cli/tests/snapshots/compile_success_empty/regression_bignum/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/compile_success_empty/regression_bignum/execute__tests__expanded.snap @@ -53,8 +53,8 @@ unconstrained fn shl(shift: u32) -> [u64; 6] { result[num_shifted_limbs] = 1_u64 << limb_shift; for i in 1_u32..6_u32 - num_shifted_limbs { { - let i_4373: u32 = i + num_shifted_limbs; - result[i_4373] = 0_u64; + let i_4392: u32 = i + num_shifted_limbs; + result[i_4392] = 0_u64; } } result diff --git a/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_1/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_1/execute__tests__expanded.snap index 811ee335159..e927fdd818a 100644 --- a/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_1/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_1/execute__tests__expanded.snap @@ -25,8 +25,8 @@ where } for i in 0_u32..b.len() { { - let i_4375: u32 = i + a.len(); - array[i_4375] = b[i]; + let i_4394: u32 = i + a.len(); + array[i_4394] = b[i]; } } array diff --git a/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_4/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_4/execute__tests__expanded.snap index 908a06c0fff..31c5ebf9d79 100644 --- a/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_4/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_4/execute__tests__expanded.snap @@ -25,8 +25,8 @@ where } for i in 0_u32..b.len() { { - let i_4375: u32 = i + a.len(); - array[i_4375] = b[i]; + let i_4394: u32 = i + a.len(); + array[i_4394] = b[i]; } } array diff --git a/tooling/nargo_cli/tests/snapshots/compile_success_no_bug/ram_blowup_regression/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/compile_success_no_bug/ram_blowup_regression/execute__tests__expanded.snap index 66fc33e9f18..963dd43bf9c 100644 --- a/tooling/nargo_cli/tests/snapshots/compile_success_no_bug/ram_blowup_regression/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/compile_success_no_bug/ram_blowup_regression/execute__tests__expanded.snap @@ -29,8 +29,8 @@ fn main(tx_effects_hash_input: [Field; 256]) -> pub Field { let input_as_bytes: [u8; 32] = tx_effects_hash_input[offset].to_be_bytes(); for byte_index in 0_u32..32_u32 { { - let i_4367: u32 = (offset * 32_u32) + byte_index; - hash_input_flattened[i_4367] = input_as_bytes[byte_index]; + let i_4386: u32 = (offset * 32_u32) + byte_index; + hash_input_flattened[i_4386] = input_as_bytes[byte_index]; } } } diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/aes128_encrypt/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/execution_success/aes128_encrypt/execute__tests__expanded.snap index ba087b955cd..a1f191d9ab8 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/aes128_encrypt/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/aes128_encrypt/execute__tests__expanded.snap @@ -18,8 +18,8 @@ unconstrained fn decode_hex(s: str) -> [u8; M] { for i in 0_u32..N { if (i % 2_u32) != 0_u32 { continue; }; { - let i_4367: u32 = i / 2_u32; - result[i_4367] = + let i_4386: u32 = i / 2_u32; + result[i_4386] = (decode_ascii(as_bytes[i]) * 16_u8) + decode_ascii(as_bytes[i + 1_u32]); } } diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/array_dedup_regression/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/execution_success/array_dedup_regression/execute__tests__expanded.snap index 2c6aed348d3..73d9d580232 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/array_dedup_regression/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/array_dedup_regression/execute__tests__expanded.snap @@ -7,8 +7,8 @@ unconstrained fn main(x: u32) { for i in 0_u32..5_u32 { let mut a2: [Field; 5] = [1_Field, 2_Field, 3_Field, 4_Field, 5_Field]; { - let i_4354: u32 = x + i; - a2[i_4354] = 128_Field; + let i_4373: u32 = x + i; + a2[i_4373] = 128_Field; }; println(a2); if i != 0_u32 { diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/array_dynamic_blackbox_input/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/execution_success/array_dynamic_blackbox_input/execute__tests__expanded.snap index 9321b3bcd79..36af1533178 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/array_dynamic_blackbox_input/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/array_dynamic_blackbox_input/execute__tests__expanded.snap @@ -17,12 +17,12 @@ fn compute_root(leaf: [u8; 32], path: [u8; 64], _index: u32, root: [u8; 32]) { let b: u32 = if is_right { 0_u32 } else { 32_u32 }; for j in 0_u32..32_u32 { { - let i_4368: u32 = j + a; - hash_input[i_4368] = current[j]; + let i_4387: u32 = j + a; + hash_input[i_4387] = current[j]; }; { - let i_4369: u32 = j + b; - hash_input[i_4369] = path[offset + j]; + let i_4388: u32 = j + b; + hash_input[i_4388] = path[offset + j]; } } current = std::hash::blake3(hash_input); diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/array_dynamic_nested_blackbox_input/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/execution_success/array_dynamic_nested_blackbox_input/execute__tests__expanded.snap index 438b5a82f86..379b233da63 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/array_dynamic_nested_blackbox_input/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/array_dynamic_nested_blackbox_input/execute__tests__expanded.snap @@ -14,13 +14,13 @@ struct Foo { fn main(mut x: [Foo; 3], y: pub u32, hash_result: pub [u8; 32]) { { - let i_4353: u32 = y - 1_u32; - x[i_4353].bar.inner = [106_u8, 107_u8, 10_u8]; + let i_4372: u32 = y - 1_u32; + x[i_4372].bar.inner = [106_u8, 107_u8, 10_u8]; }; let mut hash_input: [u8; 3] = x[y - 1_u32].bar.inner; { - let i_4355: u32 = y - 1_u32; - hash_input[i_4355] = 0_u8; + let i_4374: u32 = y - 1_u32; + hash_input[i_4374] = 0_u8; }; let hash: [u8; 32] = std::hash::blake3(hash_input); assert(hash == hash_result); diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/brillig_cow/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/execution_success/brillig_cow/execute__tests__expanded.snap index cb1fbeeb6dd..cae387b6c78 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/brillig_cow/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/brillig_cow/execute__tests__expanded.snap @@ -22,8 +22,8 @@ fn modify_in_inlined_constrained(original: [Field; 5], index: u32) -> ExecutionR modified[index] = 27_Field; let modified_once: [Field; 5] = modified; { - let i_4365: u32 = index + 1_u32; - modified[i_4365] = 27_Field; + let i_4384: u32 = index + 1_u32; + modified[i_4384] = 27_Field; }; ExecutionResult { original: original, modified_once: modified_once, modified_twice: modified } } @@ -33,8 +33,8 @@ unconstrained fn modify_in_unconstrained(original: [Field; 5], index: u32) -> Ex modified[index] = 27_Field; let modified_once: [Field; 5] = modified; { - let i_4368: u32 = index + 1_u32; - modified[i_4368] = 27_Field; + let i_4387: u32 = index + 1_u32; + modified[i_4387] = 27_Field; }; ExecutionResult { original: original, modified_once: modified_once, modified_twice: modified } } diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/brillig_cow_regression/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/execution_success/brillig_cow_regression/execute__tests__expanded.snap index 5499dd61c25..50dcccbcb3c 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/brillig_cow_regression/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/brillig_cow_regression/execute__tests__expanded.snap @@ -155,33 +155,33 @@ unconstrained fn main(kernel_data: DataToHash) -> pub [Field; 2] { let mut offset: u32 = 0_u32; for j in 0_u32..MAX_NOTE_HASHES_PER_TX { { - let i_4377: u32 = offset + j; - tx_effects_hash_inputs[i_4377] = new_note_hashes[j]; + let i_4396: u32 = offset + j; + tx_effects_hash_inputs[i_4396] = new_note_hashes[j]; } } offset = offset + MAX_NOTE_HASHES_PER_TX; for j in 0_u32..MAX_NULLIFIERS_PER_TX { { - let i_4379: u32 = offset + j; - tx_effects_hash_inputs[i_4379] = new_nullifiers[j]; + let i_4398: u32 = offset + j; + tx_effects_hash_inputs[i_4398] = new_nullifiers[j]; } } offset = offset + MAX_NULLIFIERS_PER_TX; for j in 0_u32..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { { - let i_4381: u32 = offset + (j * 2_u32); - tx_effects_hash_inputs[i_4381] = public_data_update_requests[j].leaf_slot; + let i_4400: u32 = offset + (j * 2_u32); + tx_effects_hash_inputs[i_4400] = public_data_update_requests[j].leaf_slot; }; { - let i_4382: u32 = (offset + (j * 2_u32)) + 1_u32; - tx_effects_hash_inputs[i_4382] = public_data_update_requests[j].new_value; + let i_4401: u32 = (offset + (j * 2_u32)) + 1_u32; + tx_effects_hash_inputs[i_4401] = public_data_update_requests[j].new_value; } } offset = offset + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2_u32); for j in 0_u32..MAX_L2_TO_L1_MSGS_PER_TX { { - let i_4384: u32 = offset + j; - tx_effects_hash_inputs[i_4384] = l2ToL1Msgs[j]; + let i_4403: u32 = offset + j; + tx_effects_hash_inputs[i_4403] = l2ToL1Msgs[j]; } } offset = offset + MAX_L2_TO_L1_MSGS_PER_TX; @@ -191,21 +191,21 @@ unconstrained fn main(kernel_data: DataToHash) -> pub [Field; 2] { let new_contracts: [NewContractData; 1] = kernel_data.new_contracts; tx_effects_hash_inputs[offset] = new_contracts[0_u32].contract_address; { - let i_4387: u32 = offset + 1_u32; - tx_effects_hash_inputs[i_4387] = new_contracts[0_u32].portal_contract_address; + let i_4406: u32 = offset + 1_u32; + tx_effects_hash_inputs[i_4406] = new_contracts[0_u32].portal_contract_address; }; offset = offset + (MAX_NEW_CONTRACTS_PER_TX * 2_u32); for j in 0_u32..NUM_FIELDS_PER_SHA256 { { - let i_4389: u32 = offset + j; - tx_effects_hash_inputs[i_4389] = encryptedLogsHash[j]; + let i_4408: u32 = offset + j; + tx_effects_hash_inputs[i_4408] = encryptedLogsHash[j]; } } offset = offset + (NUM_ENCRYPTED_LOGS_HASHES_PER_TX * NUM_FIELDS_PER_SHA256); for j in 0_u32..NUM_FIELDS_PER_SHA256 { { - let i_4391: u32 = offset + j; - tx_effects_hash_inputs[i_4391] = unencryptedLogsHash[j]; + let i_4410: u32 = offset + j; + tx_effects_hash_inputs[i_4410] = unencryptedLogsHash[j]; } } offset = offset + (NUM_UNENCRYPTED_LOGS_HASHES_PER_TX * NUM_FIELDS_PER_SHA256); @@ -215,8 +215,8 @@ unconstrained fn main(kernel_data: DataToHash) -> pub [Field; 2] { let input_as_bytes: [u8; 32] = tx_effects_hash_inputs[offset].to_be_bytes(); for byte_index in 0_u32..32_u32 { { - let i_4396: u32 = (offset * 32_u32) + byte_index; - hash_input_flattened[i_4396] = input_as_bytes[byte_index]; + let i_4415: u32 = (offset * 32_u32) + byte_index; + hash_input_flattened[i_4415] = input_as_bytes[byte_index]; } } } @@ -225,11 +225,11 @@ unconstrained fn main(kernel_data: DataToHash) -> pub [Field; 2] { tx_effects_hash_inputs[TX_EFFECT_HASH_FULL_FIELDS + log_field_index].to_be_bytes(); for byte_index in 0_u32..16_u32 { { - let i_4400: u32 = ( + let i_4419: u32 = ( (TX_EFFECT_HASH_FULL_FIELDS * 32_u32) + (log_field_index * 16_u32) ) + byte_index; - hash_input_flattened[i_4400] = input_as_bytes[byte_index]; + hash_input_flattened[i_4419] = input_as_bytes[byte_index]; } } } diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/conditional_1/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/execution_success/conditional_1/execute__tests__expanded.snap index fcb11876979..3953ca12c69 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/conditional_1/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/conditional_1/execute__tests__expanded.snap @@ -27,8 +27,8 @@ fn main(a: u32, mut c: [u32; 4], x: [u8; 5], result: pub [u8; 32]) { if i_u32 == a { for j in 0_u32..4_u32 { { - let i_4366: u32 = i + j; - data[i_4366] = c[(4_u32 - 1_u32) - j]; + let i_4385: u32 = i + j; + data[i_4385] = c[(4_u32 - 1_u32) - j]; }; for k in 0_u32..4_u32 { ba = ba + data[k]; diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/databus_two_calldata/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/execution_success/databus_two_calldata/execute__tests__expanded.snap index c29e5cb57aa..b647fda7e00 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/databus_two_calldata/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/databus_two_calldata/execute__tests__expanded.snap @@ -9,8 +9,8 @@ fn main(mut x: [u32; 4], y: [u32; 3], z: [u32; 4]) -> return_data [u32; 4] { result[idx] = y[idx] + z[idx]; } { - let i_4356: u32 = x[3_u32]; - result[i_4356] = z[x[3_u32]]; + let i_4375: u32 = x[3_u32]; + result[i_4375] = z[x[3_u32]]; }; result } diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/encrypted_log_regression/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/execution_success/encrypted_log_regression/execute__tests__expanded.snap index 2a53dc10714..f5cc1cdda2d 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/encrypted_log_regression/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/encrypted_log_regression/execute__tests__expanded.snap @@ -39,15 +39,15 @@ fn compute_encrypted_log( if flag { for i in 0_u32..EPH_PK_SIZE { { - let i_4369: u32 = offset + i; - encrypted_bytes[i_4369] = eph_pk_bytes[i]; + let i_4388: u32 = offset + i; + encrypted_bytes[i_4388] = eph_pk_bytes[i]; } } offset = offset + EPH_PK_SIZE; for i in 0_u32..HEADER_SIZE { { - let i_4371: u32 = offset + i; - encrypted_bytes[i_4371] = incoming_header_ciphertext[i]; + let i_4390: u32 = offset + i; + encrypted_bytes[i_4390] = incoming_header_ciphertext[i]; } } offset = offset + HEADER_SIZE; @@ -56,8 +56,8 @@ fn compute_encrypted_log( assert(size == incoming_body_ciphertext.len(), "ciphertext length mismatch"); for i in 0_u32..size { { - let i_4374: u32 = offset + i; - encrypted_bytes[i_4374] = incoming_body_ciphertext[i]; + let i_4393: u32 = offset + i; + encrypted_bytes[i_4393] = incoming_body_ciphertext[i]; } } }; diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/nested_array_dynamic/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/execution_success/nested_array_dynamic/execute__tests__expanded.snap index 877912611d9..a436e732c68 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/nested_array_dynamic/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/nested_array_dynamic/execute__tests__expanded.snap @@ -35,13 +35,13 @@ fn main(mut x: [Foo; 4], y: pub u32) { assert(x[3_u32].a == 50_Field); if y == 2_u32 { { - let i_4352: u32 = y - 1_u32; - x[i_4352].b = [50_Field, 51_Field, 52_Field]; + let i_4371: u32 = y - 1_u32; + x[i_4371].b = [50_Field, 51_Field, 52_Field]; } } else { { - let i_4353: u32 = y - 1_u32; - x[i_4353].b = [100_Field, 101_Field, 102_Field]; + let i_4372: u32 = y - 1_u32; + x[i_4372].b = [100_Field, 101_Field, 102_Field]; } }; assert(x[2_u32].b == [100_Field, 101_Field, 102_Field]); @@ -60,39 +60,39 @@ fn main(mut x: [Foo; 4], y: pub u32) { assert(foo_parents[1_u32].foos[1_u32].b == [5_Field, 6_Field, 21_Field]); if y == 2_u32 { { - let i_4357: u32 = y - 2_u32; - let i_4358: u32 = y - 2_u32; - foo_parents[i_4357].foos[i_4358].b = [10_Field, 9_Field, 8_Field]; + let i_4376: u32 = y - 2_u32; + let i_4377: u32 = y - 2_u32; + foo_parents[i_4376].foos[i_4377].b = [10_Field, 9_Field, 8_Field]; } } else { { - let i_4359: u32 = y - 2_u32; - let i_4360: u32 = y - 2_u32; - foo_parents[i_4359].foos[i_4360].b = [20_Field, 19_Field, 18_Field]; + let i_4378: u32 = y - 2_u32; + let i_4379: u32 = y - 2_u32; + foo_parents[i_4378].foos[i_4379].b = [20_Field, 19_Field, 18_Field]; } }; assert(foo_parents[1_u32].foos[1_u32].b == [20_Field, 19_Field, 18_Field]); assert(foo_parents[1_u32].foos[1_u32].b[2_u32] == 18_Field); if y == 3_u32 { { - let i_4361: u32 = y - 2_u32; - let i_4362: u32 = y - 2_u32; - let i_4363: u32 = y - 1_u32; - foo_parents[i_4361].foos[i_4362].b[i_4363] = 5000_Field; + let i_4380: u32 = y - 2_u32; + let i_4381: u32 = y - 2_u32; + let i_4382: u32 = y - 1_u32; + foo_parents[i_4380].foos[i_4381].b[i_4382] = 5000_Field; } } else { { - let i_4364: u32 = y - 2_u32; - let i_4365: u32 = y - 2_u32; - let i_4366: u32 = y - 1_u32; - foo_parents[i_4364].foos[i_4365].b[i_4366] = 1000_Field; + let i_4383: u32 = y - 2_u32; + let i_4384: u32 = y - 2_u32; + let i_4385: u32 = y - 1_u32; + foo_parents[i_4383].foos[i_4384].b[i_4385] = 1000_Field; } }; assert(foo_parents[1_u32].foos[1_u32].b[2_u32] == 5000_Field); { - let i_4367: u32 = y - 2_u32; - let i_4368: u32 = y - 3_u32; - foo_parents[i_4367].foos[i_4368].b = foo_parents[y - 2_u32].foos[y - 2_u32].b; + let i_4386: u32 = y - 2_u32; + let i_4387: u32 = y - 3_u32; + foo_parents[i_4386].foos[i_4387].b = foo_parents[y - 2_u32].foos[y - 2_u32].b; }; assert(foo_parents[1_u32].foos[0_u32].b == [20_Field, 19_Field, 5000_Field]); } diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/nested_array_in_slice/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/execution_success/nested_array_in_slice/execute__tests__expanded.snap index 2af05b0c062..d6130805e3b 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/nested_array_in_slice/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/nested_array_in_slice/execute__tests__expanded.snap @@ -48,25 +48,25 @@ fn main(y: u32) { assert(x[y].bar.inner == [109_Field, 110_Field, 111_Field]); if y != 2_u32 { { - let i_4356: u32 = y - 2_u32; - x[i_4356].a = 50_Field; + let i_4375: u32 = y - 2_u32; + x[i_4375].a = 50_Field; } } else { { - let i_4357: u32 = y - 2_u32; - x[i_4357].a = 100_Field; + let i_4376: u32 = y - 2_u32; + x[i_4376].a = 100_Field; } }; assert(x[y - 2_u32].a == 50_Field); if y == 2_u32 { { - let i_4358: u32 = y - 1_u32; - x[i_4358].b = [50_Field, 51_Field, 52_Field]; + let i_4377: u32 = y - 1_u32; + x[i_4377].b = [50_Field, 51_Field, 52_Field]; } } else { { - let i_4359: u32 = y - 1_u32; - x[i_4359].b = [100_Field, 101_Field, 102_Field]; + let i_4378: u32 = y - 1_u32; + x[i_4378].b = [100_Field, 101_Field, 102_Field]; } }; assert(x[2_u32].b == [100_Field, 101_Field, 102_Field]); diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/regression_1144_1169_2399_6609/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/execution_success/regression_1144_1169_2399_6609/execute__tests__expanded.snap index 7a1e124dd64..3629c77751b 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/regression_1144_1169_2399_6609/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/regression_1144_1169_2399_6609/execute__tests__expanded.snap @@ -36,12 +36,12 @@ fn compact_decode(input: [u8; N], length: Field) -> ([U4; 16], Field if (i as u32) < (length as u32) { let x: u8 = input[i]; { - let i_4378: u32 = (2_u32 * i) - 1_u32; - nibble[i_4378] = U4::from_u8(x >> 4_u8); + let i_4397: u32 = (2_u32 * i) - 1_u32; + nibble[i_4397] = U4::from_u8(x >> 4_u8); }; { - let i_4379: u32 = 2_u32 * i; - nibble[i_4379] = U4::from_u8(x & 15_u8); + let i_4398: u32 = 2_u32 * i; + nibble[i_4398] = U4::from_u8(x & 15_u8); } } } @@ -50,12 +50,12 @@ fn compact_decode(input: [u8; N], length: Field) -> ([U4; 16], Field if (i as u32) < ((length as u32) - 1_u32) { let x: u8 = input[i + 1_u32]; { - let i_4382: u32 = 2_u32 * i; - nibble[i_4382] = U4::from_u8(x >> 4_u8); + let i_4401: u32 = 2_u32 * i; + nibble[i_4401] = U4::from_u8(x >> 4_u8); }; { - let i_4383: u32 = (2_u32 * i) + 1_u32; - nibble[i_4383] = U4::from_u8(x & 15_u8); + let i_4402: u32 = (2_u32 * i) + 1_u32; + nibble[i_4402] = U4::from_u8(x & 15_u8); } } } diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/regression_6674_1/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/execution_success/regression_6674_1/execute__tests__expanded.snap index 7c998b8868d..7760a5734e5 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/regression_6674_1/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/regression_6674_1/execute__tests__expanded.snap @@ -16,8 +16,8 @@ impl BoundedVec4 { pub fn push(&mut self, elem: Field) { { - let i_4372: u32 = self.len; - self.storage[i_4372] = elem; + let i_4391: u32 = self.len; + self.storage[i_4391] = elem; }; self.len = self.len + 1_u32; } diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/regression_6674_2/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/execution_success/regression_6674_2/execute__tests__expanded.snap index 2bad79cf14f..f3aabacea97 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/regression_6674_2/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/regression_6674_2/execute__tests__expanded.snap @@ -16,8 +16,8 @@ impl BoundedVec4 { pub fn push(&mut self, elem: Field) { { - let i_4372: u32 = self.len; - self.storage[i_4372] = elem; + let i_4391: u32 = self.len; + self.storage[i_4391] = elem; }; self.len = self.len + 1_u32; } diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/regression_capacity_tracker/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/execution_success/regression_capacity_tracker/execute__tests__expanded.snap index ec72e4b7725..353fea94f3d 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/regression_capacity_tracker/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/regression_capacity_tracker/execute__tests__expanded.snap @@ -8,13 +8,13 @@ fn main(expected: pub Field, first: Field, input: [Field; 20]) { assert(hasher_slice[0_u32] == expected); if (expected as u32) > 10_u32 { { - let i_4354: u32 = (expected - 10_Field) as u32; - hasher_slice[i_4354] = 100_Field; + let i_4373: u32 = (expected - 10_Field) as u32; + hasher_slice[i_4373] = 100_Field; } } else { { - let i_4355: u32 = expected as u32; - hasher_slice[i_4355] = 100_Field; + let i_4374: u32 = expected as u32; + hasher_slice[i_4374] = 100_Field; } }; assert(hasher_slice[0_u32] == expected); diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/slice_dynamic_index/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/execution_success/slice_dynamic_index/execute__tests__expanded.snap index db5b7117a1a..e3cf4d99295 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/slice_dynamic_index/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/slice_dynamic_index/execute__tests__expanded.snap @@ -36,8 +36,8 @@ fn dynamic_slice_index_set_if(mut slice: [Field], x: u32, y: u32) { assert(slice[x] == 4_Field); slice[x] = slice[x] - 2_Field; { - let i_4398: u32 = x - 1_u32; - slice[i_4398] = slice[x]; + let i_4417: u32 = x - 1_u32; + slice[i_4417] = slice[x]; } } else { slice[x] = 0_Field; @@ -56,8 +56,8 @@ fn dynamic_slice_index_set_else(mut slice: [Field], x: u32, y: u32) { assert(slice[x] == 4_Field); slice[x] = slice[x] - 2_Field; { - let i_4399: u32 = x - 1_u32; - slice[i_4399] = slice[x]; + let i_4418: u32 = x - 1_u32; + slice[i_4418] = slice[x]; } } else { slice[x] = 0_Field; diff --git a/tooling/noir_js/test/node/execute.test.ts b/tooling/noir_js/test/node/execute.test.ts index 23f7e2d4a24..ca9a1ad7616 100644 --- a/tooling/noir_js/test/node/execute.test.ts +++ b/tooling/noir_js/test/node/execute.test.ts @@ -12,6 +12,7 @@ import { expect } from 'chai'; const assert_lt_program = assert_lt_json as CompiledCircuit; const assert_msg_runtime = assert_msg_json as CompiledCircuit; const fold_fibonacci_program = fold_fibonacci_json as CompiledCircuit; +const assert_raw_payload = assert_raw_payload_json as CompiledCircuit; const databus_program = databus_json as CompiledCircuit; const assert_inside_brillig_nested = assert_inside_brillig_nested_json as CompiledCircuit; @@ -83,8 +84,9 @@ it('circuit with a raw assert payload should fail with the decoded payload', asy y: '5', }; try { - await new Noir(assert_raw_payload_json).execute(inputs); + await new Noir(assert_raw_payload).execute(inputs); } catch (error) { + console.log(error); const knownError = error as ErrorWithPayload; const invalidXYErrorSelector = Object.keys(assert_raw_payload_json.abi.error_types)[0]; expect(knownError.rawAssertionPayload!.selector).to.equal(invalidXYErrorSelector); diff --git a/tooling/noirc_abi_wasm/src/lib.rs b/tooling/noirc_abi_wasm/src/lib.rs index 009de268292..2cf5517edb8 100644 --- a/tooling/noirc_abi_wasm/src/lib.rs +++ b/tooling/noirc_abi_wasm/src/lib.rs @@ -4,7 +4,7 @@ use getrandom as _; use acvm::{ - FieldElement, + AcirField, FieldElement, acir::native_types::{WitnessMap, WitnessStack}, pwg::RawAssertionPayload, }; @@ -137,17 +137,24 @@ pub fn abi_decode_error( let mut abi: Abi = JsValueSerdeExt::into_serde(&JsValue::from(abi)).map_err(|err| err.to_string())?; - let raw_error: RawAssertionPayload = + let raw_error: RawAssertionPayload = JsValueSerdeExt::into_serde(&JsValue::from(raw_error)).map_err(|err| err.to_string())?; + // `FieldElement` is represented as a string in JS so we must convert these into `FieldElements` manually. + let error_data = raw_error + .data + .iter() + .map(|field| FieldElement::from_hex(field)) + .collect::>>() + .unwrap(); let error_type = abi.error_types.remove(&raw_error.selector).expect("Missing error type"); match error_type { AbiErrorType::FmtString { .. } => { - let string = display_abi_error(&raw_error.data, error_type).to_string(); + let string = display_abi_error(&error_data, error_type).to_string(); Ok(JsValue::from_str(&string)) } AbiErrorType::Custom(typ) => { - let input_value = decode_value(&mut raw_error.data.into_iter(), &typ)?; + let input_value = decode_value(&mut error_data.into_iter(), &typ)?; let json_types = JsonTypes::try_from_input_value(&input_value, &typ)?; ::from_serde(&json_types) .map_err(|err| err.to_string().into()) diff --git a/tooling/noirc_artifacts/src/contract.rs b/tooling/noirc_artifacts/src/contract.rs index 3c9fdb1d326..fab5f6c9d87 100644 --- a/tooling/noirc_artifacts/src/contract.rs +++ b/tooling/noirc_artifacts/src/contract.rs @@ -1,4 +1,7 @@ -use acvm::{FieldElement, acir::circuit::Program}; +use acvm::{ + FieldElement, + acir::circuit::{ExpressionWidth, Program}, +}; use noirc_abi::{Abi, AbiType, AbiValue}; use noirc_driver::{CompiledContract, CompiledContractOutputs, CompiledProgram, ContractFunction}; use serde::{Deserialize, Serialize}; @@ -87,9 +90,8 @@ pub struct ContractFunctionArtifact { deserialize_with = "ProgramDebugInfo::deserialize_compressed_base64_json" )] pub debug_symbols: ProgramDebugInfo, - #[serde(default)] // For backwards compatibility (it was missing). - pub names: Vec, - pub brillig_names: Vec, + /// Maximum width of the expressions which will be constrained + pub expression_width: ExpressionWidth, } impl ContractFunctionArtifact { @@ -106,8 +108,7 @@ impl ContractFunctionArtifact { debug: self.debug_symbols.debug_infos, file_map, warnings: Vec::new(), - names: self.names, - brillig_names: self.brillig_names, + expression_width: self.expression_width, } } } @@ -121,9 +122,8 @@ impl From for ContractFunctionArtifact { custom_attributes: func.custom_attributes, abi: func.abi, bytecode: func.bytecode, - names: func.names, - brillig_names: func.brillig_names, debug_symbols: ProgramDebugInfo { debug_infos: func.debug }, + expression_width: func.expression_width, } } } diff --git a/tooling/noirc_artifacts/src/program.rs b/tooling/noirc_artifacts/src/program.rs index f90fc928067..8f77dac45e0 100644 --- a/tooling/noirc_artifacts/src/program.rs +++ b/tooling/noirc_artifacts/src/program.rs @@ -1,6 +1,7 @@ use std::collections::BTreeMap; use acvm::FieldElement; +use acvm::acir::circuit::ExpressionWidth; use acvm::acir::circuit::Program; use fm::FileId; use noirc_abi::Abi; @@ -37,10 +38,8 @@ pub struct ProgramArtifact { /// Map of file Id to the source code so locations in debug info can be mapped to source code they point to. pub file_map: BTreeMap, - - pub names: Vec, - /// Names of the unconstrained functions in the program. - pub brillig_names: Vec, + /// Maximum width of the expressions which will be constrained + pub expression_width: ExpressionWidth, } impl From for ProgramArtifact { @@ -52,8 +51,7 @@ impl From for ProgramArtifact { bytecode: compiled_program.program, debug_symbols: ProgramDebugInfo { debug_infos: compiled_program.debug }, file_map: compiled_program.file_map, - names: compiled_program.names, - brillig_names: compiled_program.brillig_names, + expression_width: compiled_program.expression_width, } } } @@ -68,8 +66,7 @@ impl From for CompiledProgram { debug: program.debug_symbols.debug_infos, file_map: program.file_map, warnings: vec![], - names: program.names, - brillig_names: program.brillig_names, + expression_width: program.expression_width, } } } diff --git a/tooling/noirc_artifacts_info/src/lib.rs b/tooling/noirc_artifacts_info/src/lib.rs index c8f299e20b8..94d99604c0b 100644 --- a/tooling/noirc_artifacts_info/src/lib.rs +++ b/tooling/noirc_artifacts_info/src/lib.rs @@ -2,7 +2,7 @@ use acvm::acir::circuit::ExpressionWidth; use iter_extended::vecmap; use noirc_artifacts::program::ProgramArtifact; use prettytable::{Row, row, table}; -use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator}; +use rayon::iter::{IntoParallelIterator, ParallelIterator}; use serde::Serialize; #[derive(Debug, Default, Serialize)] @@ -65,18 +65,20 @@ pub fn count_opcodes_and_gates_in_program( .bytecode .functions .into_par_iter() - .enumerate() - .map(|(i, function)| FunctionInfo { - name: compiled_program.names[i].clone(), + .map(|function| FunctionInfo { + name: function.function_name.clone(), opcodes: function.opcodes.len(), }) .collect(); - let opcodes_len: Vec = compiled_program + let unconstrained_info: Vec = compiled_program .bytecode .unconstrained_functions .iter() - .map(|func| func.bytecode.len()) + .map(|function| FunctionInfo { + name: function.function_name.clone(), + opcodes: function.bytecode.len(), + }) .collect(); let unconstrained_functions_opcodes = compiled_program .bytecode @@ -84,13 +86,6 @@ pub fn count_opcodes_and_gates_in_program( .into_par_iter() .map(|function| function.bytecode.len()) .sum(); - let unconstrained_info: Vec = compiled_program - .brillig_names - .clone() - .iter() - .zip(opcodes_len) - .map(|(name, len)| FunctionInfo { name: name.clone(), opcodes: len }) - .collect(); ProgramInfo { package_name, diff --git a/tooling/profiler/src/cli/execution_flamegraph_cmd.rs b/tooling/profiler/src/cli/execution_flamegraph_cmd.rs index 2d9a85fe339..710fafdef66 100644 --- a/tooling/profiler/src/cli/execution_flamegraph_cmd.rs +++ b/tooling/profiler/src/cli/execution_flamegraph_cmd.rs @@ -234,7 +234,10 @@ mod tests { hash: 27, abi: noirc_abi::Abi::default(), bytecode: Program { - functions: vec![Circuit::default()], + functions: vec![Circuit { + function_name: "main".to_string(), + ..Circuit::default() + }], unconstrained_functions: vec![ BrilligBytecode::default(), BrilligBytecode::default(), @@ -242,8 +245,7 @@ mod tests { }, debug_symbols: ProgramDebugInfo { debug_infos: vec![DebugInfo::default()] }, file_map: BTreeMap::default(), - names: vec!["main".to_string()], - brillig_names: Vec::new(), + expression_width: acir::circuit::ExpressionWidth::Bounded { width: 4 }, }; // Write the artifact to a file diff --git a/tooling/profiler/src/cli/gates_flamegraph_cmd.rs b/tooling/profiler/src/cli/gates_flamegraph_cmd.rs index 513e79c478f..b669eea6e0a 100644 --- a/tooling/profiler/src/cli/gates_flamegraph_cmd.rs +++ b/tooling/profiler/src/cli/gates_flamegraph_cmd.rs @@ -66,10 +66,7 @@ fn run_with_provider( let backend_gates_response = gates_provider.get_gates(artifact_path).context("Error querying backend for gates")?; - let function_names = std::mem::take(&mut program.names); - let bytecode = std::mem::take(&mut program.bytecode); - let debug_artifact: DebugArtifact = program.into(); let num_functions = bytecode.functions.len(); @@ -79,9 +76,9 @@ fn run_with_provider( // We can have repeated names if there are functions with the same name in different // modules or functions that use generics. Thus, add the unique function index as a suffix. let function_name = if num_functions > 1 { - format!("{}_{}", function_names[func_idx].as_str(), func_idx) + format!("{}_{}", circuit.function_name.as_str(), func_idx) } else { - function_names[func_idx].to_owned() + circuit.function_name.to_owned() }; println!( @@ -185,11 +182,16 @@ mod tests { noir_version: "0.0.0".to_string(), hash: 27, abi: noirc_abi::Abi::default(), - bytecode: Program { functions: vec![Circuit::default()], ..Program::default() }, + bytecode: Program { + functions: vec![Circuit { + function_name: "main".to_string(), + ..Circuit::default() + }], + ..Program::default() + }, debug_symbols: ProgramDebugInfo { debug_infos: vec![DebugInfo::default()] }, file_map: BTreeMap::default(), - names: vec!["main".to_string()], - brillig_names: Vec::new(), + expression_width: acir::circuit::ExpressionWidth::Bounded { width: 4 }, }; // Write the artifact to a file diff --git a/tooling/profiler/src/cli/opcodes_flamegraph_cmd.rs b/tooling/profiler/src/cli/opcodes_flamegraph_cmd.rs index ac35278bbc8..2e8862d7c56 100644 --- a/tooling/profiler/src/cli/opcodes_flamegraph_cmd.rs +++ b/tooling/profiler/src/cli/opcodes_flamegraph_cmd.rs @@ -46,20 +46,16 @@ fn run_with_generator( let mut program = read_program_from_file(artifact_path).context("Error reading program from file")?; - let acir_names = std::mem::take(&mut program.names); - let brillig_names = std::mem::take(&mut program.brillig_names); - let bytecode = std::mem::take(&mut program.bytecode); - let debug_artifact: DebugArtifact = program.into(); for (func_idx, circuit) in bytecode.functions.iter().enumerate() { // We can have repeated names if there are functions with the same name in different // modules or functions that use generics. Thus, add the unique function index as a suffix. let function_name = if bytecode.functions.len() > 1 { - format!("{}_{}", acir_names[func_idx].as_str(), func_idx) + format!("{}_{}", circuit.function_name.as_str(), func_idx) } else { - acir_names[func_idx].to_owned() + circuit.function_name.to_owned() }; println!("Opcode count for {}: {}", function_name, circuit.opcodes.len()); @@ -102,7 +98,7 @@ fn run_with_generator( // We can have repeated names if there are functions with the same name in different // modules or functions that use generics. Thus, add the unique function index as a suffix. let function_name = - format!("{}_{}", brillig_names[brillig_fn_index].as_str(), brillig_fn_index); + format!("{}_{}", brillig_bytecode.function_name.as_str(), brillig_fn_index); println!("Opcode count for {}_brillig: {}", function_name, brillig_bytecode.bytecode.len()); @@ -157,7 +153,7 @@ mod tests { use acir::{ FieldElement, circuit::{ - Circuit, Opcode, Program, + Circuit, ExpressionWidth, Opcode, Program, brillig::{BrilligBytecode, BrilligFunctionId}, }, }; @@ -200,11 +196,16 @@ mod tests { noir_version: "0.0.0".to_string(), hash: 27, abi: noirc_abi::Abi::default(), - bytecode: Program { functions: vec![Circuit::default()], ..Program::default() }, + bytecode: Program { + functions: vec![Circuit { + function_name: "main".to_string(), + ..Circuit::default() + }], + ..Program::default() + }, debug_symbols: ProgramDebugInfo { debug_infos: vec![DebugInfo::default()] }, file_map: BTreeMap::default(), - names: vec!["main".to_string()], - brillig_names: Vec::new(), + expression_width: ExpressionWidth::Bounded { width: 4 }, }; // Write the artifact to a file @@ -253,17 +254,23 @@ mod tests { hash: 27, abi: noirc_abi::Abi::default(), bytecode: Program { - functions: vec![Circuit { opcodes: acir, ..Circuit::default() }], + functions: vec![Circuit { + function_name: "main".to_string(), + opcodes: acir, + ..Circuit::default() + }], unconstrained_functions: vec![ - BrilligBytecode::default(), - BrilligBytecode::default(), - BrilligBytecode::default(), + BrilligBytecode { function_name: "main".to_string(), bytecode: Vec::default() }, + BrilligBytecode { function_name: "main".to_string(), bytecode: Vec::default() }, + BrilligBytecode { + function_name: "main_1".to_string(), + bytecode: Vec::default(), + }, ], }, debug_symbols: ProgramDebugInfo { debug_infos: vec![DebugInfo::default()] }, file_map: BTreeMap::default(), - names: vec!["main".to_string()], - brillig_names: vec!["main".to_string(), "main".to_string(), "main_1".to_string()], + expression_width: ExpressionWidth::Bounded { width: 4 }, }; // Write the artifact to a file diff --git a/tooling/profiler/src/opcode_formatter.rs b/tooling/profiler/src/opcode_formatter.rs index 0b7278acb2f..5ab50647917 100644 --- a/tooling/profiler/src/opcode_formatter.rs +++ b/tooling/profiler/src/opcode_formatter.rs @@ -16,12 +16,6 @@ fn format_blackbox_function(call: &BlackBoxFuncCall) -> String BlackBoxFuncCall::EmbeddedCurveAdd { .. } => "embedded_curve_add".to_string(), BlackBoxFuncCall::Keccakf1600 { .. } => "keccakf1600".to_string(), BlackBoxFuncCall::RecursiveAggregation { .. } => "recursive_aggregation".to_string(), - BlackBoxFuncCall::BigIntAdd { .. } => "big_int_add".to_string(), - BlackBoxFuncCall::BigIntSub { .. } => "big_int_sub".to_string(), - BlackBoxFuncCall::BigIntMul { .. } => "big_int_mul".to_string(), - BlackBoxFuncCall::BigIntDiv { .. } => "big_int_div".to_string(), - BlackBoxFuncCall::BigIntFromLeBytes { .. } => "big_int_from_le_bytes".to_string(), - BlackBoxFuncCall::BigIntToLeBytes { .. } => "big_int_to_le_bytes".to_string(), BlackBoxFuncCall::Poseidon2Permutation { .. } => "poseidon2_permutation".to_string(), BlackBoxFuncCall::Sha256Compression { .. } => "sha256_compression".to_string(), } @@ -37,12 +31,6 @@ fn format_blackbox_op(call: &BlackBoxOp) -> String { BlackBoxOp::MultiScalarMul { .. } => "multi_scalar_mul".to_string(), BlackBoxOp::EmbeddedCurveAdd { .. } => "embedded_curve_add".to_string(), BlackBoxOp::Keccakf1600 { .. } => "keccakf1600".to_string(), - BlackBoxOp::BigIntAdd { .. } => "big_int_add".to_string(), - BlackBoxOp::BigIntSub { .. } => "big_int_sub".to_string(), - BlackBoxOp::BigIntMul { .. } => "big_int_mul".to_string(), - BlackBoxOp::BigIntDiv { .. } => "big_int_div".to_string(), - BlackBoxOp::BigIntFromLeBytes { .. } => "big_int_from_le_bytes".to_string(), - BlackBoxOp::BigIntToLeBytes { .. } => "big_int_to_le_bytes".to_string(), BlackBoxOp::Poseidon2Permutation { .. } => "poseidon2_permutation".to_string(), BlackBoxOp::Sha256Compression { .. } => "sha256_compression".to_string(), BlackBoxOp::ToRadix { .. } => "to_radix".to_string(), @@ -109,7 +97,6 @@ fn format_brillig_opcode_kind(opcode: &BrilligOpcode) -> String { BrilligOpcode::ForeignCall { function, .. } => format!("foreign_call({function})"), BrilligOpcode::Jump { .. } => "jump".to_string(), BrilligOpcode::JumpIf { .. } => "jump_if".to_string(), - BrilligOpcode::JumpIfNot { .. } => "jump_if_not".to_string(), BrilligOpcode::Load { .. } => "load".to_string(), BrilligOpcode::Mov { .. } => "mov".to_string(), BrilligOpcode::Return => "return".to_string(), diff --git a/tooling/ssa_executor/src/compiler.rs b/tooling/ssa_executor/src/compiler.rs index 2d9634a9444..ce841ea71d6 100644 --- a/tooling/ssa_executor/src/compiler.rs +++ b/tooling/ssa_executor/src/compiler.rs @@ -71,14 +71,13 @@ pub fn compile_from_artifacts(artifacts: ArtifactsAndWarnings) -> CompiledProgra .map(|acir| vec![(acir.input_witnesses.len() as u32, Visibility::Private)]) .collect(); - let SsaProgramArtifact { program, debug, warnings, names, brillig_names, .. } = - combine_artifacts( - artifacts, - &dummy_arg_info, - BTreeMap::new(), - BTreeMap::new(), - BTreeMap::new(), - ); + let SsaProgramArtifact { program, debug, warnings, .. } = combine_artifacts( + artifacts, + &dummy_arg_info, + BTreeMap::new(), + BTreeMap::new(), + BTreeMap::new(), + ); let file_map = BTreeMap::new(); CompiledProgram { hash: 1, // const hash, doesn't matter in this case @@ -88,8 +87,7 @@ pub fn compile_from_artifacts(artifacts: ArtifactsAndWarnings) -> CompiledProgra file_map, noir_version: NOIR_ARTIFACT_VERSION_STRING.to_string(), warnings, - names, - brillig_names, + expression_width: noirc_driver::DEFAULT_EXPRESSION_WIDTH, } } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/block_context.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/block_context.rs index 906d1915a07..4dd14786366 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/block_context.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/block_context.rs @@ -603,7 +603,7 @@ impl BlockContext { } } } - Instruction::PointAdd { p1, p2 } => { + Instruction::PointAdd { p1, p2, predicate } => { if !self.options.instruction_options.point_add_enabled { return; } @@ -614,12 +614,12 @@ impl BlockContext { } let p1 = p1.unwrap(); let p2 = p2.unwrap(); - let acir_point = builder.point_add(p1.clone(), p2.clone()); + let acir_point = builder.point_add(p1.clone(), p2.clone(), predicate); for typed_value in [&acir_point.x, &acir_point.y, &acir_point.is_infinite] { self.store_variable(typed_value); } } - Instruction::MultiScalarMul { points_and_scalars } => { + Instruction::MultiScalarMul { points_and_scalars, predicate } => { if !self.options.instruction_options.multi_scalar_mul_enabled { return; } @@ -640,7 +640,8 @@ impl BlockContext { if points_vec.len() != scalars_vec.len() { unreachable!("points_vec.len() != scalars_vec.len()"); } - let point = builder.multi_scalar_mul(points_vec.clone(), scalars_vec.clone()); + let point = + builder.multi_scalar_mul(points_vec.clone(), scalars_vec.clone(), predicate); for typed_value in [&point.x, &point.y, &point.is_infinite] { self.store_variable(typed_value); } @@ -651,6 +652,7 @@ impl BlockContext { corrupt_pubkey_x, corrupt_pubkey_y, corrupt_signature, + predicate, } => { if !self.options.instruction_options.ecdsa_secp256r1_enabled { return; @@ -668,6 +670,7 @@ impl BlockContext { prepared_signature.public_key_y.clone(), prepared_signature.hash.clone(), prepared_signature.signature.clone(), + predicate, ); self.store_variable(&result); } @@ -677,6 +680,7 @@ impl BlockContext { corrupt_pubkey_x, corrupt_pubkey_y, corrupt_signature, + predicate, } => { if !self.options.instruction_options.ecdsa_secp256k1_enabled { return; @@ -694,6 +698,7 @@ impl BlockContext { prepared_signature.public_key_y.clone(), prepared_signature.hash.clone(), prepared_signature.signature.clone(), + predicate, ); self.store_variable(&result); } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/instruction.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/instruction.rs index 73e08149cab..a0c431adbe4 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/instruction.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/instruction.rs @@ -160,10 +160,10 @@ pub(crate) enum Instruction { }, /// Point addition - PointAdd { p1: Point, p2: Point }, + PointAdd { p1: Point, p2: Point, predicate: bool }, /// Multi-scalar multiplication - MultiScalarMul { points_and_scalars: Vec }, + MultiScalarMul { points_and_scalars: Vec, predicate: bool }, /// ECDSA secp256r1 EcdsaSecp256r1 { @@ -172,6 +172,7 @@ pub(crate) enum Instruction { corrupt_pubkey_x: bool, corrupt_pubkey_y: bool, corrupt_signature: bool, + predicate: bool, }, /// ECDSA secp256k1 @@ -181,6 +182,7 @@ pub(crate) enum Instruction { corrupt_pubkey_x: bool, corrupt_pubkey_y: bool, corrupt_signature: bool, + predicate: bool, }, } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/ecdsa.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/ecdsa.rs index 54693ed7cae..6df1c66faca 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/ecdsa.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/ecdsa.rs @@ -18,6 +18,7 @@ fn test_valid_ecdsa_signature_secp256r1() { corrupt_pubkey_x: false, corrupt_pubkey_y: false, corrupt_signature: false, + predicate: true, }; let block = InstructionBlock { instructions: vec![instruction] }; let commands = vec![]; @@ -46,6 +47,7 @@ fn test_valid_ecdsa_signature_secp256k1() { corrupt_pubkey_x: false, corrupt_pubkey_y: false, corrupt_signature: false, + predicate: true, }; let block = InstructionBlock { instructions: vec![instruction] }; let commands = vec![]; @@ -65,7 +67,6 @@ fn test_valid_ecdsa_signature_secp256k1() { } #[test] -#[should_panic] fn test_corrupted_ecdsa_signature_secp256r1() { let _ = env_logger::try_init(); let msg = [122, 97, 109, 97, 121]; @@ -75,6 +76,7 @@ fn test_corrupted_ecdsa_signature_secp256r1() { corrupt_pubkey_x: true, corrupt_pubkey_y: true, corrupt_signature: true, + predicate: true, }; let block = InstructionBlock { instructions: vec![instruction] }; let commands = vec![]; @@ -101,7 +103,6 @@ fn test_corrupted_ecdsa_signature_secp256r1() { } #[test] -#[should_panic] fn test_corrupted_ecdsa_signature_secp256k1() { let _ = env_logger::try_init(); let msg = [122, 97, 109, 97, 121]; @@ -111,6 +112,7 @@ fn test_corrupted_ecdsa_signature_secp256k1() { corrupt_pubkey_x: true, corrupt_pubkey_y: true, corrupt_signature: true, + predicate: true, }; let block = InstructionBlock { instructions: vec![instruction] }; let commands = vec![]; diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/embedded_curve_ops.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/embedded_curve_ops.rs index f918b018975..849f60234f8 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/embedded_curve_ops.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/embedded_curve_ops.rs @@ -31,6 +31,7 @@ fn smoke_test_embedded_curve_add() { derive_from_scalar_mul: true, is_infinite: false, }, + predicate: true, }; let block = InstructionBlock { instructions: vec![add_instruction] }; let commands = vec![]; @@ -76,6 +77,7 @@ fn smoke_test_embedded_multi_scalar_mul() { let gen_point = Point { scalar: base_scalar, derive_from_scalar_mul: true, is_infinite: false }; let instruction = Instruction::MultiScalarMul { points_and_scalars: vec![(gen_point, scalar_1), (gen_point, scalar_2)], + predicate: true, }; let block = InstructionBlock { instructions: vec![instruction] }; let commands = vec![]; diff --git a/tooling/ssa_fuzzer/fuzzer/src/mutations/instructions/instruction_block_mutator.rs b/tooling/ssa_fuzzer/fuzzer/src/mutations/instructions/instruction_block_mutator.rs index 442dda32884..f67be5bdff2 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/mutations/instructions/instruction_block_mutator.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/mutations/instructions/instruction_block_mutator.rs @@ -167,10 +167,13 @@ fn generate_random_instruction(rng: &mut StdRng) -> Instruction { (generate_random_point(rng), generate_random_scalar(rng)), (generate_random_point(rng), generate_random_scalar(rng)), ], + predicate: true, + }, + GenerateInstruction::PointAdd => Instruction::PointAdd { + p1: generate_random_point(rng), + p2: generate_random_point(rng), + predicate: true, }, - GenerateInstruction::PointAdd => { - Instruction::PointAdd { p1: generate_random_point(rng), p2: generate_random_point(rng) } - } GenerateInstruction::EcdsaSecp256r1 => { let mut msg = [0; SIZE_OF_LARGE_ARBITRARY_BUFFER]; @@ -184,6 +187,7 @@ fn generate_random_instruction(rng: &mut StdRng) -> Instruction { rng, GENERATE_BOOL_CONFIGURATION_MOST_FALSE, ), + predicate: true, } } GenerateInstruction::EcdsaSecp256k1 => { @@ -198,6 +202,7 @@ fn generate_random_instruction(rng: &mut StdRng) -> Instruction { rng, GENERATE_BOOL_CONFIGURATION_MOST_FALSE, ), + predicate: true, } } } diff --git a/tooling/ssa_fuzzer/fuzzer/src/mutations/instructions/instruction_mutator.rs b/tooling/ssa_fuzzer/fuzzer/src/mutations/instructions/instruction_mutator.rs index 37f18a0478c..a20931c5387 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/mutations/instructions/instruction_mutator.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/mutations/instructions/instruction_mutator.rs @@ -277,7 +277,7 @@ impl InstructionArgumentsMutation { } } } - Instruction::PointAdd { p1, p2 } => { + Instruction::PointAdd { p1, p2, .. } => { match BASIC_INSTRUCTION_ARGUMENT_MUTATION_CONFIGURATION.select(rng) { InstructionArgumentMutationOptions::Left => { mutate_point(p1, rng); @@ -288,7 +288,7 @@ impl InstructionArgumentsMutation { } } - Instruction::MultiScalarMul { points_and_scalars } => { + Instruction::MultiScalarMul { points_and_scalars, .. } => { mutate_vec( points_and_scalars, rng, @@ -306,6 +306,7 @@ impl InstructionArgumentsMutation { corrupt_pubkey_x, corrupt_pubkey_y, corrupt_signature, + .. } | Instruction::EcdsaSecp256r1 { msg, @@ -313,6 +314,7 @@ impl InstructionArgumentsMutation { corrupt_pubkey_x, corrupt_pubkey_y, corrupt_signature, + .. } => { mutate_vec( msg, diff --git a/tooling/ssa_fuzzer/src/builder.rs b/tooling/ssa_fuzzer/src/builder.rs index c1e3e4d5701..4f65154be03 100644 --- a/tooling/ssa_fuzzer/src/builder.rs +++ b/tooling/ssa_fuzzer/src/builder.rs @@ -789,9 +789,10 @@ impl FuzzerBuilder { Arc::new(vec![field_type.clone(), field_type.clone(), boolean_type.clone()]), 1, ); + let predicate = self.builder.numeric_constant(1_u32, NumericType::Boolean.into()); let result = self.builder.insert_call( intrinsic, - vec![basic_point, scalar_id], + vec![basic_point, scalar_id, predicate], vec![return_type.clone().into()], ); assert_eq!(result.len(), 1); @@ -830,7 +831,12 @@ impl FuzzerBuilder { Point { x: scalar.lo, y: scalar.hi, is_infinite } } - pub fn multi_scalar_mul(&mut self, points: Vec, scalars: Vec) -> Point { + pub fn multi_scalar_mul( + &mut self, + points: Vec, + scalars: Vec, + predicate: bool, + ) -> Point { assert_eq!(points.len(), scalars.len()); for point in &points { assert!(point.validate()); @@ -838,7 +844,8 @@ impl FuzzerBuilder { for scalar in &scalars { assert!(scalar.validate()); } - + let predicate = + self.builder.numeric_constant(u32::from(predicate), NumericType::Boolean.into()); let field_type = Type::Numeric(NumericType::Field); let boolean_type = Type::Numeric(NumericType::Boolean); let intrinsic = self @@ -871,7 +878,7 @@ impl FuzzerBuilder { ); let result = self.builder.insert_call( intrinsic, - vec![point_ids_array, scalar_ids_array], + vec![point_ids_array, scalar_ids_array, predicate], vec![return_type.clone().into()], ); assert_eq!(result.len(), 1); @@ -904,22 +911,25 @@ impl FuzzerBuilder { } } - pub fn point_add(&mut self, p1: Point, p2: Point) -> Point { + pub fn point_add(&mut self, p1: Point, p2: Point, predicate: bool) -> Point { assert!(p1.validate()); assert!(p2.validate()); let field_type = Type::Numeric(NumericType::Field); let boolean_type = Type::Numeric(NumericType::Boolean); + let predicate = + self.builder.numeric_constant(u32::from(predicate), NumericType::Boolean.into()); let intrinsic = self .builder .import_intrinsic("embedded_curve_add") .expect("embedded_curve_add intrinsic should be available"); - let points_flattened = p1.to_id_vec().into_iter().chain(p2.to_id_vec()).collect::>(); + let mut arguments = p1.to_id_vec().into_iter().chain(p2.to_id_vec()).collect::>(); + arguments.push(predicate); let return_type = Type::Array( Arc::new(vec![field_type.clone(), field_type.clone(), boolean_type.clone()]), 1, ); let result = - self.builder.insert_call(intrinsic, points_flattened, vec![return_type.clone().into()]); + self.builder.insert_call(intrinsic, arguments, vec![return_type.clone().into()]); assert_eq!(result.len(), 1); let result = result[0]; let x_idx = self.builder.numeric_constant(0_u32, NumericType::U32.into()); @@ -963,28 +973,19 @@ impl FuzzerBuilder { ) } - fn bytes_to_ssa_slice(&mut self, vec: Vec) -> TypedValue { - let elements: Vec> = vec - .into_iter() - .map(|x| self.builder.numeric_constant(u32::from(x), NumericType::U8.into())) - .collect(); - let slice_type = Type::Slice(Arc::new(vec![Type::Numeric(NumericType::U8)])); - TypedValue::new( - self.builder.insert_make_array(elements.into(), slice_type.clone().into()), - slice_type, - ) - } - pub fn ecdsa_secp256r1( &mut self, pub_key_x: Vec, pub_key_y: Vec, hash: Vec, signature: Vec, + predicate: bool, ) -> TypedValue { + let predicate = + self.builder.numeric_constant(u32::from(predicate), NumericType::Boolean.into()); let pub_key_x = self.bytes_to_ssa_array(pub_key_x); let pub_key_y = self.bytes_to_ssa_array(pub_key_y); - let hash = self.bytes_to_ssa_slice(hash); + let hash = self.bytes_to_ssa_array(hash); let signature = self.bytes_to_ssa_array(signature); let return_type = Type::Numeric(NumericType::Boolean); let intrinsic = self @@ -993,7 +994,13 @@ impl FuzzerBuilder { .expect("ecdsa_secp256r1 intrinsic should be available"); let result = self.builder.insert_call( intrinsic, - vec![pub_key_x.value_id, pub_key_y.value_id, signature.value_id, hash.value_id], + vec![ + pub_key_x.value_id, + pub_key_y.value_id, + signature.value_id, + hash.value_id, + predicate, + ], vec![return_type.clone().into()], ); assert_eq!(result.len(), 1); @@ -1007,10 +1014,13 @@ impl FuzzerBuilder { pub_key_y: Vec, hash: Vec, signature: Vec, + predicate: bool, ) -> TypedValue { + let predicate = + self.builder.numeric_constant(u32::from(predicate), NumericType::Boolean.into()); let pub_key_x = self.bytes_to_ssa_array(pub_key_x); let pub_key_y = self.bytes_to_ssa_array(pub_key_y); - let hash = self.bytes_to_ssa_slice(hash); + let hash = self.bytes_to_ssa_array(hash); let signature = self.bytes_to_ssa_array(signature); let return_type = Type::Numeric(NumericType::Boolean); let intrinsic = self @@ -1019,7 +1029,13 @@ impl FuzzerBuilder { .expect("ecdsa_secp256k1 intrinsic should be available"); let result = self.builder.insert_call( intrinsic, - vec![pub_key_x.value_id, pub_key_y.value_id, signature.value_id, hash.value_id], + vec![ + pub_key_x.value_id, + pub_key_y.value_id, + signature.value_id, + hash.value_id, + predicate, + ], vec![return_type.clone().into()], ); assert_eq!(result.len(), 1); diff --git a/tooling/ssa_verification/src/acir_instruction_builder.rs b/tooling/ssa_verification/src/acir_instruction_builder.rs index 1f97af255fa..f8d4fe304d5 100644 --- a/tooling/ssa_verification/src/acir_instruction_builder.rs +++ b/tooling/ssa_verification/src/acir_instruction_builder.rs @@ -246,7 +246,7 @@ fn ssa_to_acir_program(ssa: Ssa) -> AcirProgram { enable_brillig_constraints_check_lookback: false, skip_passes: vec![], }; - let (acir_functions, brillig, _, _) = match optimize_ssa_builder_into_acir( + let (acir_functions, brillig, _) = match optimize_ssa_builder_into_acir( builder, &ssa_evaluator_options, &primary_passes(&ssa_evaluator_options), diff --git a/yarn.lock b/yarn.lock index fdde8c37785..bbfcc73e1c0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -238,9 +238,9 @@ __metadata: languageName: node linkType: hard -"@aztec/bb.js@npm:1.2.0": - version: 1.2.0 - resolution: "@aztec/bb.js@npm:1.2.0" +"@aztec/bb.js@npm:v3.0.0-nightly.20250916": + version: 3.0.0-nightly.20250916 + resolution: "@aztec/bb.js@npm:3.0.0-nightly.20250916" dependencies: comlink: "npm:^4.4.1" commander: "npm:^12.1.0" @@ -251,7 +251,7 @@ __metadata: tslib: "npm:^2.4.0" bin: bb.js: dest/node/main.js - checksum: 10/a3b7d15f2d47079433c8ef5b546123177c7bd074bc48198baf21a8f697531fc96a69e8b3f60d8ba8446b206310d3d058beb8bdcd2c387c6044996775842edeb4 + checksum: 10/82b846ba847eaa37c062eeb75e3f2e8c5eabd9990ad47260ddc39912c3d11da018ef8260bec7b002f60527d2e1cb8d2d32b4a5e4de3078cb78e0b82d3f4894ce languageName: node linkType: hard @@ -15739,7 +15739,7 @@ __metadata: version: 0.0.0-use.local resolution: "docs_tutorials_browser@workspace:examples/browser" dependencies: - "@aztec/bb.js": "npm:1.2.0" + "@aztec/bb.js": "npm:v3.0.0-nightly.20250916" "@noir-lang/noir_js": "workspace:*" "@playwright/test": "npm:^1.49.0" "@types/node": "npm:^20.0.0" @@ -19118,7 +19118,7 @@ __metadata: version: 0.0.0-use.local resolution: "integration-tests@workspace:compiler/integration-tests" dependencies: - "@aztec/bb.js": "npm:1.2.0" + "@aztec/bb.js": "npm:v3.0.0-nightly.20250916" "@noir-lang/noir_js": "workspace:*" "@noir-lang/noir_wasm": "workspace:*" "@nomicfoundation/hardhat-chai-matchers": "npm:^2.0.8"