From b64b09b17e20f7047117c40e2fa4a7ec6e7876d5 Mon Sep 17 00:00:00 2001 From: guipublic Date: Tue, 16 Jan 2024 18:11:21 +0000 Subject: [PATCH 1/9] Add big int opcodes (without implementation) --- .../dsl/acir_format/serde/acir.hpp | 1314 +++++++++++++---- noir/acvm-repo/acir/codegen/acir.cpp | 644 +++++++- .../acir/src/circuit/black_box_functions.rs | 25 + .../opcodes/black_box_function_call.rs | 58 +- .../acvm/src/compiler/transformers/mod.rs | 14 +- noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs | 6 + noir/acvm-repo/brillig/src/black_box.rs | 79 +- noir/acvm-repo/brillig_vm/src/black_box.rs | 12 + .../brillig/brillig_gen/brillig_black_box.rs | 101 ++ .../src/brillig/brillig_ir/debug_show.rs | 53 + .../ssa/acir_gen/acir_ir/generated_acir.rs | 62 + .../src/ssa/ir/instruction/call.rs | 9 +- 12 files changed, 2102 insertions(+), 275 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp index c85f609bbd1..e568a7e5404 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp @@ -206,6 +206,65 @@ struct BlackBoxFuncCall { static RecursiveAggregation bincodeDeserialize(std::vector); }; + struct BigIntAdd { + Circuit::FunctionInput lhs; + Circuit::FunctionInput rhs; + Circuit::Witness output; + + friend bool operator==(const BigIntAdd&, const BigIntAdd&); + std::vector bincodeSerialize() const; + static BigIntAdd bincodeDeserialize(std::vector); + }; + + struct BigIntNeg { + Circuit::FunctionInput lhs; + Circuit::FunctionInput rhs; + Circuit::Witness output; + + friend bool operator==(const BigIntNeg&, const BigIntNeg&); + std::vector bincodeSerialize() const; + static BigIntNeg bincodeDeserialize(std::vector); + }; + + struct BigIntMul { + Circuit::FunctionInput lhs; + Circuit::FunctionInput rhs; + Circuit::Witness output; + + friend bool operator==(const BigIntMul&, const BigIntMul&); + std::vector bincodeSerialize() const; + static BigIntMul bincodeDeserialize(std::vector); + }; + + struct BigIntDiv { + Circuit::FunctionInput lhs; + Circuit::FunctionInput rhs; + Circuit::Witness output; + + friend bool operator==(const BigIntDiv&, const BigIntDiv&); + std::vector bincodeSerialize() const; + static BigIntDiv bincodeDeserialize(std::vector); + }; + + struct BigIntFromLeBytes { + std::vector inputs; + std::vector modulus; + Circuit::Witness output; + + friend bool operator==(const BigIntFromLeBytes&, const BigIntFromLeBytes&); + std::vector bincodeSerialize() const; + static BigIntFromLeBytes bincodeDeserialize(std::vector); + }; + + struct BigIntToLeBytes { + Circuit::FunctionInput input; + std::vector outputs; + + friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); + std::vector bincodeSerialize() const; + static BigIntToLeBytes bincodeDeserialize(std::vector); + }; + std::variant + RecursiveAggregation, + BigIntAdd, + BigIntNeg, + BigIntMul, + BigIntDiv, + BigIntFromLeBytes, + BigIntToLeBytes> value; friend bool operator==(const BlackBoxFuncCall&, const BlackBoxFuncCall&); @@ -239,8 +304,6 @@ struct BlockId { static BlockId bincodeDeserialize(std::vector); }; -// TODO(https://github.com/AztecProtocol/barretenberg/issues/825): This struct is more general than it needs / should be -// allowed to be. We can only accommodate 1 quadratic term and 3 linear terms. struct Expression { std::vector> mul_terms; std::vector> linear_combinations; @@ -563,6 +626,65 @@ struct BlackBoxOp { static EmbeddedCurveDouble bincodeDeserialize(std::vector); }; + struct BigIntAdd { + Circuit::RegisterIndex lhs; + Circuit::RegisterIndex rhs; + Circuit::RegisterIndex output; + + friend bool operator==(const BigIntAdd&, const BigIntAdd&); + std::vector bincodeSerialize() const; + static BigIntAdd bincodeDeserialize(std::vector); + }; + + struct BigIntNeg { + Circuit::RegisterIndex lhs; + Circuit::RegisterIndex rhs; + Circuit::RegisterIndex output; + + friend bool operator==(const BigIntNeg&, const BigIntNeg&); + std::vector bincodeSerialize() const; + static BigIntNeg bincodeDeserialize(std::vector); + }; + + struct BigIntMul { + Circuit::RegisterIndex lhs; + Circuit::RegisterIndex rhs; + Circuit::RegisterIndex output; + + friend bool operator==(const BigIntMul&, const BigIntMul&); + std::vector bincodeSerialize() const; + static BigIntMul bincodeDeserialize(std::vector); + }; + + struct BigIntDiv { + Circuit::RegisterIndex lhs; + Circuit::RegisterIndex rhs; + Circuit::RegisterIndex output; + + friend bool operator==(const BigIntDiv&, const BigIntDiv&); + std::vector bincodeSerialize() const; + static BigIntDiv bincodeDeserialize(std::vector); + }; + + struct BigIntFromLeBytes { + Circuit::HeapVector inputs; + Circuit::HeapVector modulus; + Circuit::RegisterIndex output; + + friend bool operator==(const BigIntFromLeBytes&, const BigIntFromLeBytes&); + std::vector bincodeSerialize() const; + static BigIntFromLeBytes bincodeDeserialize(std::vector); + }; + + struct BigIntToLeBytes { + Circuit::RegisterIndex input; + Circuit::HeapVector output; + + friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); + std::vector bincodeSerialize() const; + static BigIntToLeBytes bincodeDeserialize(std::vector); + }; + std::variant + EmbeddedCurveDouble, + BigIntAdd, + BigIntNeg, + BigIntMul, + BigIntDiv, + BigIntFromLeBytes, + BigIntToLeBytes> value; friend bool operator==(const BlackBoxOp&, const BlackBoxOp&); @@ -2883,25 +3011,31 @@ Circuit::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable< namespace Circuit { -inline bool operator==(const BlackBoxOp& lhs, const BlackBoxOp& rhs) +inline bool operator==(const BlackBoxFuncCall::BigIntAdd& lhs, const BlackBoxFuncCall::BigIntAdd& rhs) { - if (!(lhs.value == rhs.value)) { + 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::bincodeSerialize() const +inline std::vector BlackBoxFuncCall::BigIntAdd::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } -inline BlackBoxOp BlackBoxOp::bincodeDeserialize(std::vector input) +inline BlackBoxFuncCall::BigIntAdd BlackBoxFuncCall::BigIntAdd::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"); } @@ -2912,29 +3046,34 @@ inline BlackBoxOp BlackBoxOp::bincodeDeserialize(std::vector input) template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::BigIntAdd& obj, Serializer& serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); + serde::Serializable::serialize(obj.lhs, serializer); + serde::Serializable::serialize(obj.rhs, serializer); + serde::Serializable::serialize(obj.output, serializer); } template <> template -Circuit::BlackBoxOp serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BlackBoxFuncCall::BigIntAdd serde::Deserializable::deserialize( + Deserializer& deserializer) { - deserializer.increase_container_depth(); - Circuit::BlackBoxOp obj; - obj.value = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); + Circuit::BlackBoxFuncCall::BigIntAdd obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); return obj; } namespace Circuit { -inline bool operator==(const BlackBoxOp::Sha256& lhs, const BlackBoxOp::Sha256& rhs) +inline bool operator==(const BlackBoxFuncCall::BigIntNeg& lhs, const BlackBoxFuncCall::BigIntNeg& rhs) { - if (!(lhs.message == rhs.message)) { + if (!(lhs.lhs == rhs.lhs)) { + return false; + } + if (!(lhs.rhs == rhs.rhs)) { return false; } if (!(lhs.output == rhs.output)) { @@ -2943,17 +3082,17 @@ inline bool operator==(const BlackBoxOp::Sha256& lhs, const BlackBoxOp::Sha256& return true; } -inline std::vector BlackBoxOp::Sha256::bincodeSerialize() const +inline std::vector BlackBoxFuncCall::BigIntNeg::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } -inline BlackBoxOp::Sha256 BlackBoxOp::Sha256::bincodeDeserialize(std::vector input) +inline BlackBoxFuncCall::BigIntNeg BlackBoxFuncCall::BigIntNeg::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"); } @@ -2964,28 +3103,34 @@ inline BlackBoxOp::Sha256 BlackBoxOp::Sha256::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Sha256& obj, - Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::BigIntNeg& obj, Serializer& serializer) { - serde::Serializable::serialize(obj.message, serializer); + serde::Serializable::serialize(obj.lhs, serializer); + serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); } template <> template -Circuit::BlackBoxOp::Sha256 serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BlackBoxFuncCall::BigIntNeg serde::Deserializable::deserialize( + Deserializer& deserializer) { - Circuit::BlackBoxOp::Sha256 obj; - obj.message = serde::Deserializable::deserialize(deserializer); + Circuit::BlackBoxFuncCall::BigIntNeg obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } namespace Circuit { -inline bool operator==(const BlackBoxOp::Blake2s& lhs, const BlackBoxOp::Blake2s& rhs) +inline bool operator==(const BlackBoxFuncCall::BigIntMul& lhs, const BlackBoxFuncCall::BigIntMul& rhs) { - if (!(lhs.message == rhs.message)) { + if (!(lhs.lhs == rhs.lhs)) { + return false; + } + if (!(lhs.rhs == rhs.rhs)) { return false; } if (!(lhs.output == rhs.output)) { @@ -2994,17 +3139,17 @@ inline bool operator==(const BlackBoxOp::Blake2s& lhs, const BlackBoxOp::Blake2s return true; } -inline std::vector BlackBoxOp::Blake2s::bincodeSerialize() const +inline std::vector BlackBoxFuncCall::BigIntMul::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } -inline BlackBoxOp::Blake2s BlackBoxOp::Blake2s::bincodeDeserialize(std::vector input) +inline BlackBoxFuncCall::BigIntMul BlackBoxFuncCall::BigIntMul::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"); } @@ -3015,29 +3160,34 @@ inline BlackBoxOp::Blake2s BlackBoxOp::Blake2s::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Blake2s& obj, - Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::BigIntMul& obj, Serializer& serializer) { - serde::Serializable::serialize(obj.message, serializer); + serde::Serializable::serialize(obj.lhs, serializer); + serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); } template <> template -Circuit::BlackBoxOp::Blake2s serde::Deserializable::deserialize( +Circuit::BlackBoxFuncCall::BigIntMul serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::Blake2s obj; - obj.message = serde::Deserializable::deserialize(deserializer); + Circuit::BlackBoxFuncCall::BigIntMul obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } namespace Circuit { -inline bool operator==(const BlackBoxOp::Blake3& lhs, const BlackBoxOp::Blake3& rhs) +inline bool operator==(const BlackBoxFuncCall::BigIntDiv& lhs, const BlackBoxFuncCall::BigIntDiv& rhs) { - if (!(lhs.message == rhs.message)) { + if (!(lhs.lhs == rhs.lhs)) { + return false; + } + if (!(lhs.rhs == rhs.rhs)) { return false; } if (!(lhs.output == rhs.output)) { @@ -3046,17 +3196,17 @@ inline bool operator==(const BlackBoxOp::Blake3& lhs, const BlackBoxOp::Blake3& return true; } -inline std::vector BlackBoxOp::Blake3::bincodeSerialize() const +inline std::vector BlackBoxFuncCall::BigIntDiv::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } -inline BlackBoxOp::Blake3 BlackBoxOp::Blake3::bincodeDeserialize(std::vector input) +inline BlackBoxFuncCall::BigIntDiv BlackBoxFuncCall::BigIntDiv::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"); } @@ -3067,28 +3217,34 @@ inline BlackBoxOp::Blake3 BlackBoxOp::Blake3::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Blake3& obj, - Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::BigIntDiv& obj, Serializer& serializer) { - serde::Serializable::serialize(obj.message, serializer); + serde::Serializable::serialize(obj.lhs, serializer); + serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); } template <> template -Circuit::BlackBoxOp::Blake3 serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BlackBoxFuncCall::BigIntDiv serde::Deserializable::deserialize( + Deserializer& deserializer) { - Circuit::BlackBoxOp::Blake3 obj; - obj.message = serde::Deserializable::deserialize(deserializer); + Circuit::BlackBoxFuncCall::BigIntDiv obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } namespace Circuit { -inline bool operator==(const BlackBoxOp::Keccak256& lhs, const BlackBoxOp::Keccak256& rhs) +inline bool operator==(const BlackBoxFuncCall::BigIntFromLeBytes& lhs, const BlackBoxFuncCall::BigIntFromLeBytes& rhs) { - if (!(lhs.message == rhs.message)) { + if (!(lhs.inputs == rhs.inputs)) { + return false; + } + if (!(lhs.modulus == rhs.modulus)) { return false; } if (!(lhs.output == rhs.output)) { @@ -3097,17 +3253,18 @@ inline bool operator==(const BlackBoxOp::Keccak256& lhs, const BlackBoxOp::Kecca return true; } -inline std::vector BlackBoxOp::Keccak256::bincodeSerialize() const +inline std::vector BlackBoxFuncCall::BigIntFromLeBytes::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } -inline BlackBoxOp::Keccak256 BlackBoxOp::Keccak256::bincodeDeserialize(std::vector input) +inline BlackBoxFuncCall::BigIntFromLeBytes BlackBoxFuncCall::BigIntFromLeBytes::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"); } @@ -3118,48 +3275,51 @@ inline BlackBoxOp::Keccak256 BlackBoxOp::Keccak256::bincodeDeserialize(std::vect template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Keccak256& obj, - Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::BigIntFromLeBytes& obj, Serializer& serializer) { - serde::Serializable::serialize(obj.message, serializer); + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.modulus, serializer); serde::Serializable::serialize(obj.output, serializer); } template <> template -Circuit::BlackBoxOp::Keccak256 serde::Deserializable::deserialize( - Deserializer& deserializer) +Circuit::BlackBoxFuncCall::BigIntFromLeBytes serde::Deserializable< + Circuit::BlackBoxFuncCall::BigIntFromLeBytes>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxOp::Keccak256 obj; - obj.message = serde::Deserializable::deserialize(deserializer); + Circuit::BlackBoxFuncCall::BigIntFromLeBytes obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.modulus = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } namespace Circuit { -inline bool operator==(const BlackBoxOp::Keccakf1600& lhs, const BlackBoxOp::Keccakf1600& rhs) +inline bool operator==(const BlackBoxFuncCall::BigIntToLeBytes& lhs, const BlackBoxFuncCall::BigIntToLeBytes& rhs) { - if (!(lhs.message == rhs.message)) { + if (!(lhs.input == rhs.input)) { return false; } - if (!(lhs.output == rhs.output)) { + if (!(lhs.outputs == rhs.outputs)) { return false; } return true; } -inline std::vector BlackBoxOp::Keccakf1600::bincodeSerialize() const +inline std::vector BlackBoxFuncCall::BigIntToLeBytes::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } -inline BlackBoxOp::Keccakf1600 BlackBoxOp::Keccakf1600::bincodeDeserialize(std::vector input) +inline BlackBoxFuncCall::BigIntToLeBytes BlackBoxFuncCall::BigIntToLeBytes::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"); } @@ -3170,57 +3330,45 @@ inline BlackBoxOp::Keccakf1600 BlackBoxOp::Keccakf1600::bincodeDeserialize(std:: template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Keccakf1600& obj, - Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::BigIntToLeBytes& obj, Serializer& serializer) { - serde::Serializable::serialize(obj.message, serializer); - serde::Serializable::serialize(obj.output, serializer); + serde::Serializable::serialize(obj.input, serializer); + serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxOp::Keccakf1600 serde::Deserializable::deserialize( - Deserializer& deserializer) +Circuit::BlackBoxFuncCall::BigIntToLeBytes serde::Deserializable< + Circuit::BlackBoxFuncCall::BigIntToLeBytes>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxOp::Keccakf1600 obj; - obj.message = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); + Circuit::BlackBoxFuncCall::BigIntToLeBytes obj; + obj.input = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } namespace Circuit { -inline bool operator==(const BlackBoxOp::EcdsaSecp256k1& lhs, const BlackBoxOp::EcdsaSecp256k1& rhs) +inline bool operator==(const BlackBoxOp& lhs, const BlackBoxOp& rhs) { - if (!(lhs.hashed_msg == rhs.hashed_msg)) { - return false; - } - if (!(lhs.public_key_x == rhs.public_key_x)) { - return false; - } - if (!(lhs.public_key_y == rhs.public_key_y)) { - return false; - } - if (!(lhs.signature == rhs.signature)) { - return false; - } - if (!(lhs.result == rhs.result)) { + if (!(lhs.value == rhs.value)) { return false; } return true; } -inline std::vector BlackBoxOp::EcdsaSecp256k1::bincodeSerialize() const +inline std::vector BlackBoxOp::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } -inline BlackBoxOp::EcdsaSecp256k1 BlackBoxOp::EcdsaSecp256k1::bincodeDeserialize(std::vector input) +inline BlackBoxOp BlackBoxOp::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"); } @@ -3231,44 +3379,668 @@ inline BlackBoxOp::EcdsaSecp256k1 BlackBoxOp::EcdsaSecp256k1::bincodeDeserialize template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::EcdsaSecp256k1& obj, - Serializer& serializer) +void serde::Serializable::serialize(const Circuit::BlackBoxOp& obj, Serializer& serializer) { - serde::Serializable::serialize(obj.hashed_msg, serializer); - serde::Serializable::serialize(obj.public_key_x, serializer); - serde::Serializable::serialize(obj.public_key_y, serializer); - serde::Serializable::serialize(obj.signature, serializer); - serde::Serializable::serialize(obj.result, serializer); + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); } template <> template -Circuit::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable::deserialize( - Deserializer& deserializer) +Circuit::BlackBoxOp serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxOp::EcdsaSecp256k1 obj; - obj.hashed_msg = serde::Deserializable::deserialize(deserializer); - obj.public_key_x = serde::Deserializable::deserialize(deserializer); - obj.public_key_y = serde::Deserializable::deserialize(deserializer); - obj.signature = serde::Deserializable::deserialize(deserializer); - obj.result = serde::Deserializable::deserialize(deserializer); + deserializer.increase_container_depth(); + Circuit::BlackBoxOp obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace Circuit { + +inline bool operator==(const BlackBoxOp::Sha256& lhs, const BlackBoxOp::Sha256& rhs) +{ + if (!(lhs.message == rhs.message)) { + return false; + } + if (!(lhs.output == rhs.output)) { + return false; + } + return true; +} + +inline std::vector BlackBoxOp::Sha256::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline BlackBoxOp::Sha256 BlackBoxOp::Sha256::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 Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::BlackBoxOp::Sha256& obj, + Serializer& serializer) +{ + serde::Serializable::serialize(obj.message, serializer); + serde::Serializable::serialize(obj.output, serializer); +} + +template <> +template +Circuit::BlackBoxOp::Sha256 serde::Deserializable::deserialize(Deserializer& deserializer) +{ + Circuit::BlackBoxOp::Sha256 obj; + obj.message = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + +inline bool operator==(const BlackBoxOp::Blake2s& lhs, const BlackBoxOp::Blake2s& rhs) +{ + if (!(lhs.message == rhs.message)) { + return false; + } + if (!(lhs.output == rhs.output)) { + return false; + } + return true; +} + +inline std::vector BlackBoxOp::Blake2s::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline BlackBoxOp::Blake2s BlackBoxOp::Blake2s::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 Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::BlackBoxOp::Blake2s& obj, + Serializer& serializer) +{ + serde::Serializable::serialize(obj.message, serializer); + serde::Serializable::serialize(obj.output, serializer); +} + +template <> +template +Circuit::BlackBoxOp::Blake2s serde::Deserializable::deserialize( + Deserializer& deserializer) +{ + Circuit::BlackBoxOp::Blake2s obj; + obj.message = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + +inline bool operator==(const BlackBoxOp::Blake3& lhs, const BlackBoxOp::Blake3& rhs) +{ + if (!(lhs.message == rhs.message)) { + return false; + } + if (!(lhs.output == rhs.output)) { + return false; + } + return true; +} + +inline std::vector BlackBoxOp::Blake3::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline BlackBoxOp::Blake3 BlackBoxOp::Blake3::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 Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::BlackBoxOp::Blake3& obj, + Serializer& serializer) +{ + serde::Serializable::serialize(obj.message, serializer); + serde::Serializable::serialize(obj.output, serializer); +} + +template <> +template +Circuit::BlackBoxOp::Blake3 serde::Deserializable::deserialize(Deserializer& deserializer) +{ + Circuit::BlackBoxOp::Blake3 obj; + obj.message = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + +inline bool operator==(const BlackBoxOp::Keccak256& lhs, const BlackBoxOp::Keccak256& rhs) +{ + if (!(lhs.message == rhs.message)) { + return false; + } + if (!(lhs.output == rhs.output)) { + return false; + } + return true; +} + +inline std::vector BlackBoxOp::Keccak256::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline BlackBoxOp::Keccak256 BlackBoxOp::Keccak256::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 Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::BlackBoxOp::Keccak256& obj, + Serializer& serializer) +{ + serde::Serializable::serialize(obj.message, serializer); + serde::Serializable::serialize(obj.output, serializer); +} + +template <> +template +Circuit::BlackBoxOp::Keccak256 serde::Deserializable::deserialize( + Deserializer& deserializer) +{ + Circuit::BlackBoxOp::Keccak256 obj; + obj.message = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + +inline bool operator==(const BlackBoxOp::Keccakf1600& lhs, const BlackBoxOp::Keccakf1600& rhs) +{ + if (!(lhs.message == rhs.message)) { + return false; + } + if (!(lhs.output == rhs.output)) { + return false; + } + return true; +} + +inline std::vector BlackBoxOp::Keccakf1600::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline BlackBoxOp::Keccakf1600 BlackBoxOp::Keccakf1600::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 Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::BlackBoxOp::Keccakf1600& obj, + Serializer& serializer) +{ + serde::Serializable::serialize(obj.message, serializer); + serde::Serializable::serialize(obj.output, serializer); +} + +template <> +template +Circuit::BlackBoxOp::Keccakf1600 serde::Deserializable::deserialize( + Deserializer& deserializer) +{ + Circuit::BlackBoxOp::Keccakf1600 obj; + obj.message = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + +inline bool operator==(const BlackBoxOp::EcdsaSecp256k1& lhs, const BlackBoxOp::EcdsaSecp256k1& rhs) +{ + if (!(lhs.hashed_msg == rhs.hashed_msg)) { + return false; + } + if (!(lhs.public_key_x == rhs.public_key_x)) { + return false; + } + if (!(lhs.public_key_y == rhs.public_key_y)) { + return false; + } + if (!(lhs.signature == rhs.signature)) { + return false; + } + if (!(lhs.result == rhs.result)) { + return false; + } + return true; +} + +inline std::vector BlackBoxOp::EcdsaSecp256k1::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline BlackBoxOp::EcdsaSecp256k1 BlackBoxOp::EcdsaSecp256k1::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 Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::BlackBoxOp::EcdsaSecp256k1& obj, + Serializer& serializer) +{ + serde::Serializable::serialize(obj.hashed_msg, serializer); + serde::Serializable::serialize(obj.public_key_x, serializer); + serde::Serializable::serialize(obj.public_key_y, serializer); + serde::Serializable::serialize(obj.signature, serializer); + serde::Serializable::serialize(obj.result, serializer); +} + +template <> +template +Circuit::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable::deserialize( + Deserializer& deserializer) +{ + Circuit::BlackBoxOp::EcdsaSecp256k1 obj; + obj.hashed_msg = serde::Deserializable::deserialize(deserializer); + obj.public_key_x = serde::Deserializable::deserialize(deserializer); + obj.public_key_y = serde::Deserializable::deserialize(deserializer); + obj.signature = serde::Deserializable::deserialize(deserializer); + obj.result = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + +inline bool operator==(const BlackBoxOp::EcdsaSecp256r1& lhs, const BlackBoxOp::EcdsaSecp256r1& rhs) +{ + if (!(lhs.hashed_msg == rhs.hashed_msg)) { + return false; + } + if (!(lhs.public_key_x == rhs.public_key_x)) { + return false; + } + if (!(lhs.public_key_y == rhs.public_key_y)) { + return false; + } + if (!(lhs.signature == rhs.signature)) { + return false; + } + if (!(lhs.result == rhs.result)) { + return false; + } + return true; +} + +inline std::vector BlackBoxOp::EcdsaSecp256r1::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline BlackBoxOp::EcdsaSecp256r1 BlackBoxOp::EcdsaSecp256r1::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 Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::BlackBoxOp::EcdsaSecp256r1& obj, + Serializer& serializer) +{ + serde::Serializable::serialize(obj.hashed_msg, serializer); + serde::Serializable::serialize(obj.public_key_x, serializer); + serde::Serializable::serialize(obj.public_key_y, serializer); + serde::Serializable::serialize(obj.signature, serializer); + serde::Serializable::serialize(obj.result, serializer); +} + +template <> +template +Circuit::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable::deserialize( + Deserializer& deserializer) +{ + Circuit::BlackBoxOp::EcdsaSecp256r1 obj; + obj.hashed_msg = serde::Deserializable::deserialize(deserializer); + obj.public_key_x = serde::Deserializable::deserialize(deserializer); + obj.public_key_y = serde::Deserializable::deserialize(deserializer); + obj.signature = serde::Deserializable::deserialize(deserializer); + obj.result = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + +inline bool operator==(const BlackBoxOp::SchnorrVerify& lhs, const BlackBoxOp::SchnorrVerify& rhs) +{ + if (!(lhs.public_key_x == rhs.public_key_x)) { + return false; + } + if (!(lhs.public_key_y == rhs.public_key_y)) { + return false; + } + if (!(lhs.message == rhs.message)) { + return false; + } + if (!(lhs.signature == rhs.signature)) { + return false; + } + if (!(lhs.result == rhs.result)) { + return false; + } + return true; +} + +inline std::vector BlackBoxOp::SchnorrVerify::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline BlackBoxOp::SchnorrVerify BlackBoxOp::SchnorrVerify::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 Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::BlackBoxOp::SchnorrVerify& obj, + Serializer& serializer) +{ + serde::Serializable::serialize(obj.public_key_x, serializer); + serde::Serializable::serialize(obj.public_key_y, serializer); + serde::Serializable::serialize(obj.message, serializer); + serde::Serializable::serialize(obj.signature, serializer); + serde::Serializable::serialize(obj.result, serializer); +} + +template <> +template +Circuit::BlackBoxOp::SchnorrVerify serde::Deserializable::deserialize( + Deserializer& deserializer) +{ + Circuit::BlackBoxOp::SchnorrVerify obj; + obj.public_key_x = serde::Deserializable::deserialize(deserializer); + obj.public_key_y = serde::Deserializable::deserialize(deserializer); + obj.message = serde::Deserializable::deserialize(deserializer); + obj.signature = serde::Deserializable::deserialize(deserializer); + obj.result = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + +inline bool operator==(const BlackBoxOp::PedersenCommitment& lhs, const BlackBoxOp::PedersenCommitment& rhs) +{ + if (!(lhs.inputs == rhs.inputs)) { + return false; + } + if (!(lhs.domain_separator == rhs.domain_separator)) { + return false; + } + if (!(lhs.output == rhs.output)) { + return false; + } + return true; +} + +inline std::vector BlackBoxOp::PedersenCommitment::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline BlackBoxOp::PedersenCommitment BlackBoxOp::PedersenCommitment::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 Circuit + +template <> +template +void serde::Serializable::serialize( + const Circuit::BlackBoxOp::PedersenCommitment& obj, Serializer& serializer) +{ + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.domain_separator, serializer); + serde::Serializable::serialize(obj.output, serializer); +} + +template <> +template +Circuit::BlackBoxOp::PedersenCommitment serde::Deserializable::deserialize( + Deserializer& deserializer) +{ + Circuit::BlackBoxOp::PedersenCommitment obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.domain_separator = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + +inline bool operator==(const BlackBoxOp::PedersenHash& lhs, const BlackBoxOp::PedersenHash& rhs) +{ + if (!(lhs.inputs == rhs.inputs)) { + return false; + } + if (!(lhs.domain_separator == rhs.domain_separator)) { + return false; + } + if (!(lhs.output == rhs.output)) { + return false; + } + return true; +} + +inline std::vector BlackBoxOp::PedersenHash::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline BlackBoxOp::PedersenHash BlackBoxOp::PedersenHash::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 Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::BlackBoxOp::PedersenHash& obj, + Serializer& serializer) +{ + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.domain_separator, serializer); + serde::Serializable::serialize(obj.output, serializer); +} + +template <> +template +Circuit::BlackBoxOp::PedersenHash serde::Deserializable::deserialize( + Deserializer& deserializer) +{ + Circuit::BlackBoxOp::PedersenHash obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.domain_separator = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + +inline bool operator==(const BlackBoxOp::FixedBaseScalarMul& lhs, const BlackBoxOp::FixedBaseScalarMul& rhs) +{ + if (!(lhs.low == rhs.low)) { + return false; + } + if (!(lhs.high == rhs.high)) { + return false; + } + if (!(lhs.result == rhs.result)) { + return false; + } + return true; +} + +inline std::vector BlackBoxOp::FixedBaseScalarMul::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline BlackBoxOp::FixedBaseScalarMul BlackBoxOp::FixedBaseScalarMul::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 Circuit + +template <> +template +void serde::Serializable::serialize( + const Circuit::BlackBoxOp::FixedBaseScalarMul& obj, Serializer& serializer) +{ + serde::Serializable::serialize(obj.low, serializer); + serde::Serializable::serialize(obj.high, serializer); + serde::Serializable::serialize(obj.result, serializer); +} + +template <> +template +Circuit::BlackBoxOp::FixedBaseScalarMul serde::Deserializable::deserialize( + Deserializer& deserializer) +{ + Circuit::BlackBoxOp::FixedBaseScalarMul obj; + obj.low = serde::Deserializable::deserialize(deserializer); + obj.high = serde::Deserializable::deserialize(deserializer); + obj.result = serde::Deserializable::deserialize(deserializer); return obj; } namespace Circuit { -inline bool operator==(const BlackBoxOp::EcdsaSecp256r1& lhs, const BlackBoxOp::EcdsaSecp256r1& rhs) +inline bool operator==(const BlackBoxOp::EmbeddedCurveAdd& lhs, const BlackBoxOp::EmbeddedCurveAdd& rhs) { - if (!(lhs.hashed_msg == rhs.hashed_msg)) { + if (!(lhs.input1_x == rhs.input1_x)) { return false; } - if (!(lhs.public_key_x == rhs.public_key_x)) { + if (!(lhs.input1_y == rhs.input1_y)) { return false; } - if (!(lhs.public_key_y == rhs.public_key_y)) { + if (!(lhs.input2_x == rhs.input2_x)) { return false; } - if (!(lhs.signature == rhs.signature)) { + if (!(lhs.input2_y == rhs.input2_y)) { return false; } if (!(lhs.result == rhs.result)) { @@ -3277,17 +4049,17 @@ inline bool operator==(const BlackBoxOp::EcdsaSecp256r1& lhs, const BlackBoxOp:: return true; } -inline std::vector BlackBoxOp::EcdsaSecp256r1::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::EcdsaSecp256r1 BlackBoxOp::EcdsaSecp256r1::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"); } @@ -3298,44 +4070,38 @@ inline BlackBoxOp::EcdsaSecp256r1 BlackBoxOp::EcdsaSecp256r1::bincodeDeserialize template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::EcdsaSecp256r1& obj, - Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxOp::EmbeddedCurveAdd& obj, Serializer& serializer) { - serde::Serializable::serialize(obj.hashed_msg, serializer); - serde::Serializable::serialize(obj.public_key_x, serializer); - serde::Serializable::serialize(obj.public_key_y, serializer); - serde::Serializable::serialize(obj.signature, serializer); + serde::Serializable::serialize(obj.input1_x, serializer); + serde::Serializable::serialize(obj.input1_y, serializer); + serde::Serializable::serialize(obj.input2_x, serializer); + serde::Serializable::serialize(obj.input2_y, serializer); serde::Serializable::serialize(obj.result, serializer); } template <> template -Circuit::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable::deserialize( +Circuit::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::EcdsaSecp256r1 obj; - obj.hashed_msg = serde::Deserializable::deserialize(deserializer); - obj.public_key_x = serde::Deserializable::deserialize(deserializer); - obj.public_key_y = serde::Deserializable::deserialize(deserializer); - obj.signature = serde::Deserializable::deserialize(deserializer); + Circuit::BlackBoxOp::EmbeddedCurveAdd obj; + obj.input1_x = serde::Deserializable::deserialize(deserializer); + obj.input1_y = serde::Deserializable::deserialize(deserializer); + obj.input2_x = serde::Deserializable::deserialize(deserializer); + obj.input2_y = serde::Deserializable::deserialize(deserializer); obj.result = serde::Deserializable::deserialize(deserializer); return obj; } namespace Circuit { -inline bool operator==(const BlackBoxOp::SchnorrVerify& lhs, const BlackBoxOp::SchnorrVerify& rhs) +inline bool operator==(const BlackBoxOp::EmbeddedCurveDouble& lhs, const BlackBoxOp::EmbeddedCurveDouble& rhs) { - if (!(lhs.public_key_x == rhs.public_key_x)) { - return false; - } - if (!(lhs.public_key_y == rhs.public_key_y)) { - return false; - } - if (!(lhs.message == rhs.message)) { + if (!(lhs.input1_x == rhs.input1_x)) { return false; } - if (!(lhs.signature == rhs.signature)) { + if (!(lhs.input1_y == rhs.input1_y)) { return false; } if (!(lhs.result == rhs.result)) { @@ -3344,17 +4110,17 @@ inline bool operator==(const BlackBoxOp::SchnorrVerify& lhs, const BlackBoxOp::S return true; } -inline std::vector BlackBoxOp::SchnorrVerify::bincodeSerialize() const +inline std::vector BlackBoxOp::EmbeddedCurveDouble::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } -inline BlackBoxOp::SchnorrVerify BlackBoxOp::SchnorrVerify::bincodeDeserialize(std::vector input) +inline BlackBoxOp::EmbeddedCurveDouble BlackBoxOp::EmbeddedCurveDouble::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"); } @@ -3365,38 +4131,34 @@ inline BlackBoxOp::SchnorrVerify BlackBoxOp::SchnorrVerify::bincodeDeserialize(s template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::SchnorrVerify& obj, - Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxOp::EmbeddedCurveDouble& obj, Serializer& serializer) { - serde::Serializable::serialize(obj.public_key_x, serializer); - serde::Serializable::serialize(obj.public_key_y, serializer); - serde::Serializable::serialize(obj.message, serializer); - serde::Serializable::serialize(obj.signature, serializer); + serde::Serializable::serialize(obj.input1_x, serializer); + serde::Serializable::serialize(obj.input1_y, serializer); serde::Serializable::serialize(obj.result, serializer); } template <> template -Circuit::BlackBoxOp::SchnorrVerify serde::Deserializable::deserialize( +Circuit::BlackBoxOp::EmbeddedCurveDouble serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::SchnorrVerify obj; - obj.public_key_x = serde::Deserializable::deserialize(deserializer); - obj.public_key_y = serde::Deserializable::deserialize(deserializer); - obj.message = serde::Deserializable::deserialize(deserializer); - obj.signature = serde::Deserializable::deserialize(deserializer); + Circuit::BlackBoxOp::EmbeddedCurveDouble obj; + obj.input1_x = serde::Deserializable::deserialize(deserializer); + obj.input1_y = serde::Deserializable::deserialize(deserializer); obj.result = serde::Deserializable::deserialize(deserializer); return obj; } namespace Circuit { -inline bool operator==(const BlackBoxOp::PedersenCommitment& lhs, const BlackBoxOp::PedersenCommitment& rhs) +inline bool operator==(const BlackBoxOp::BigIntAdd& lhs, const BlackBoxOp::BigIntAdd& rhs) { - if (!(lhs.inputs == rhs.inputs)) { + if (!(lhs.lhs == rhs.lhs)) { return false; } - if (!(lhs.domain_separator == rhs.domain_separator)) { + if (!(lhs.rhs == rhs.rhs)) { return false; } if (!(lhs.output == rhs.output)) { @@ -3405,17 +4167,17 @@ inline bool operator==(const BlackBoxOp::PedersenCommitment& lhs, const BlackBox return true; } -inline std::vector BlackBoxOp::PedersenCommitment::bincodeSerialize() const +inline std::vector BlackBoxOp::BigIntAdd::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } -inline BlackBoxOp::PedersenCommitment BlackBoxOp::PedersenCommitment::bincodeDeserialize(std::vector input) +inline BlackBoxOp::BigIntAdd BlackBoxOp::BigIntAdd::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"); } @@ -3426,34 +4188,34 @@ inline BlackBoxOp::PedersenCommitment BlackBoxOp::PedersenCommitment::bincodeDes template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxOp::PedersenCommitment& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntAdd& obj, + Serializer& serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.domain_separator, serializer); + serde::Serializable::serialize(obj.lhs, serializer); + serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); } template <> template -Circuit::BlackBoxOp::PedersenCommitment serde::Deserializable::deserialize( +Circuit::BlackBoxOp::BigIntAdd serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::PedersenCommitment obj; - obj.inputs = serde::Deserializable::deserialize(deserializer); - obj.domain_separator = serde::Deserializable::deserialize(deserializer); + Circuit::BlackBoxOp::BigIntAdd obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } namespace Circuit { -inline bool operator==(const BlackBoxOp::PedersenHash& lhs, const BlackBoxOp::PedersenHash& rhs) +inline bool operator==(const BlackBoxOp::BigIntNeg& lhs, const BlackBoxOp::BigIntNeg& rhs) { - if (!(lhs.inputs == rhs.inputs)) { + if (!(lhs.lhs == rhs.lhs)) { return false; } - if (!(lhs.domain_separator == rhs.domain_separator)) { + if (!(lhs.rhs == rhs.rhs)) { return false; } if (!(lhs.output == rhs.output)) { @@ -3462,17 +4224,17 @@ inline bool operator==(const BlackBoxOp::PedersenHash& lhs, const BlackBoxOp::Pe return true; } -inline std::vector BlackBoxOp::PedersenHash::bincodeSerialize() const +inline std::vector BlackBoxOp::BigIntNeg::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } -inline BlackBoxOp::PedersenHash BlackBoxOp::PedersenHash::bincodeDeserialize(std::vector input) +inline BlackBoxOp::BigIntNeg BlackBoxOp::BigIntNeg::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"); } @@ -3483,53 +4245,53 @@ inline BlackBoxOp::PedersenHash BlackBoxOp::PedersenHash::bincodeDeserialize(std template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::PedersenHash& obj, - Serializer& serializer) +void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntNeg& obj, + Serializer& serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.domain_separator, serializer); + serde::Serializable::serialize(obj.lhs, serializer); + serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); } template <> template -Circuit::BlackBoxOp::PedersenHash serde::Deserializable::deserialize( +Circuit::BlackBoxOp::BigIntNeg serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::PedersenHash obj; - obj.inputs = serde::Deserializable::deserialize(deserializer); - obj.domain_separator = serde::Deserializable::deserialize(deserializer); + Circuit::BlackBoxOp::BigIntNeg obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } namespace Circuit { -inline bool operator==(const BlackBoxOp::FixedBaseScalarMul& lhs, const BlackBoxOp::FixedBaseScalarMul& rhs) +inline bool operator==(const BlackBoxOp::BigIntMul& lhs, const BlackBoxOp::BigIntMul& rhs) { - if (!(lhs.low == rhs.low)) { + if (!(lhs.lhs == rhs.lhs)) { return false; } - if (!(lhs.high == rhs.high)) { + if (!(lhs.rhs == rhs.rhs)) { return false; } - if (!(lhs.result == rhs.result)) { + if (!(lhs.output == rhs.output)) { return false; } return true; } -inline std::vector BlackBoxOp::FixedBaseScalarMul::bincodeSerialize() const +inline std::vector BlackBoxOp::BigIntMul::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } -inline BlackBoxOp::FixedBaseScalarMul BlackBoxOp::FixedBaseScalarMul::bincodeDeserialize(std::vector input) +inline BlackBoxOp::BigIntMul BlackBoxOp::BigIntMul::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"); } @@ -3540,59 +4302,110 @@ inline BlackBoxOp::FixedBaseScalarMul BlackBoxOp::FixedBaseScalarMul::bincodeDes template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxOp::FixedBaseScalarMul& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntMul& obj, + Serializer& serializer) { - serde::Serializable::serialize(obj.low, serializer); - serde::Serializable::serialize(obj.high, serializer); - serde::Serializable::serialize(obj.result, serializer); + serde::Serializable::serialize(obj.lhs, serializer); + serde::Serializable::serialize(obj.rhs, serializer); + serde::Serializable::serialize(obj.output, serializer); } template <> template -Circuit::BlackBoxOp::FixedBaseScalarMul serde::Deserializable::deserialize( +Circuit::BlackBoxOp::BigIntMul serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::FixedBaseScalarMul obj; - obj.low = serde::Deserializable::deserialize(deserializer); - obj.high = serde::Deserializable::deserialize(deserializer); - obj.result = serde::Deserializable::deserialize(deserializer); + Circuit::BlackBoxOp::BigIntMul obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); return obj; } namespace Circuit { -inline bool operator==(const BlackBoxOp::EmbeddedCurveAdd& lhs, const BlackBoxOp::EmbeddedCurveAdd& rhs) +inline bool operator==(const BlackBoxOp::BigIntDiv& lhs, const BlackBoxOp::BigIntDiv& rhs) { - if (!(lhs.input1_x == rhs.input1_x)) { + if (!(lhs.lhs == rhs.lhs)) { return false; } - if (!(lhs.input1_y == rhs.input1_y)) { + if (!(lhs.rhs == rhs.rhs)) { return false; } - if (!(lhs.input2_x == rhs.input2_x)) { + if (!(lhs.output == rhs.output)) { return false; } - if (!(lhs.input2_y == rhs.input2_y)) { + 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 Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::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 +Circuit::BlackBoxOp::BigIntDiv serde::Deserializable::deserialize( + Deserializer& deserializer) +{ + Circuit::BlackBoxOp::BigIntDiv obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + +inline bool operator==(const BlackBoxOp::BigIntFromLeBytes& lhs, const BlackBoxOp::BigIntFromLeBytes& rhs) +{ + if (!(lhs.inputs == rhs.inputs)) { return false; } - if (!(lhs.result == rhs.result)) { + if (!(lhs.modulus == rhs.modulus)) { + return false; + } + if (!(lhs.output == rhs.output)) { return false; } return true; } -inline std::vector BlackBoxOp::EmbeddedCurveAdd::bincodeSerialize() const +inline std::vector BlackBoxOp::BigIntFromLeBytes::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } -inline BlackBoxOp::EmbeddedCurveAdd BlackBoxOp::EmbeddedCurveAdd::bincodeDeserialize(std::vector input) +inline BlackBoxOp::BigIntFromLeBytes BlackBoxOp::BigIntFromLeBytes::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"); } @@ -3603,57 +4416,50 @@ inline BlackBoxOp::EmbeddedCurveAdd BlackBoxOp::EmbeddedCurveAdd::bincodeDeseria template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxOp::EmbeddedCurveAdd& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxOp::BigIntFromLeBytes& obj, Serializer& serializer) { - serde::Serializable::serialize(obj.input1_x, serializer); - serde::Serializable::serialize(obj.input1_y, serializer); - serde::Serializable::serialize(obj.input2_x, serializer); - serde::Serializable::serialize(obj.input2_y, serializer); - serde::Serializable::serialize(obj.result, serializer); + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.modulus, serializer); + serde::Serializable::serialize(obj.output, serializer); } template <> template -Circuit::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable::deserialize( +Circuit::BlackBoxOp::BigIntFromLeBytes serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::EmbeddedCurveAdd obj; - obj.input1_x = serde::Deserializable::deserialize(deserializer); - obj.input1_y = serde::Deserializable::deserialize(deserializer); - obj.input2_x = serde::Deserializable::deserialize(deserializer); - obj.input2_y = serde::Deserializable::deserialize(deserializer); - obj.result = serde::Deserializable::deserialize(deserializer); + Circuit::BlackBoxOp::BigIntFromLeBytes obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.modulus = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); return obj; } namespace Circuit { -inline bool operator==(const BlackBoxOp::EmbeddedCurveDouble& lhs, const BlackBoxOp::EmbeddedCurveDouble& rhs) +inline bool operator==(const BlackBoxOp::BigIntToLeBytes& lhs, const BlackBoxOp::BigIntToLeBytes& rhs) { - if (!(lhs.input1_x == rhs.input1_x)) { - return false; - } - if (!(lhs.input1_y == rhs.input1_y)) { + if (!(lhs.input == rhs.input)) { return false; } - if (!(lhs.result == rhs.result)) { + if (!(lhs.output == rhs.output)) { return false; } return true; } -inline std::vector BlackBoxOp::EmbeddedCurveDouble::bincodeSerialize() const +inline std::vector BlackBoxOp::BigIntToLeBytes::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } -inline BlackBoxOp::EmbeddedCurveDouble BlackBoxOp::EmbeddedCurveDouble::bincodeDeserialize(std::vector input) +inline BlackBoxOp::BigIntToLeBytes BlackBoxOp::BigIntToLeBytes::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"); } @@ -3664,23 +4470,21 @@ inline BlackBoxOp::EmbeddedCurveDouble BlackBoxOp::EmbeddedCurveDouble::bincodeD template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxOp::EmbeddedCurveDouble& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxOp::BigIntToLeBytes& obj, Serializer& serializer) { - serde::Serializable::serialize(obj.input1_x, serializer); - serde::Serializable::serialize(obj.input1_y, serializer); - serde::Serializable::serialize(obj.result, serializer); + serde::Serializable::serialize(obj.input, serializer); + serde::Serializable::serialize(obj.output, serializer); } template <> template -Circuit::BlackBoxOp::EmbeddedCurveDouble serde::Deserializable::deserialize( +Circuit::BlackBoxOp::BigIntToLeBytes serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::EmbeddedCurveDouble obj; - obj.input1_x = serde::Deserializable::deserialize(deserializer); - obj.input1_y = serde::Deserializable::deserialize(deserializer); - obj.result = serde::Deserializable::deserialize(deserializer); + Circuit::BlackBoxOp::BigIntToLeBytes obj; + obj.input = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); return obj; } diff --git a/noir/acvm-repo/acir/codegen/acir.cpp b/noir/acvm-repo/acir/codegen/acir.cpp index 9b74a8ea631..47675775910 100644 --- a/noir/acvm-repo/acir/codegen/acir.cpp +++ b/noir/acvm-repo/acir/codegen/acir.cpp @@ -206,7 +206,66 @@ namespace Circuit { static RecursiveAggregation bincodeDeserialize(std::vector); }; - std::variant value; + struct BigIntAdd { + Circuit::FunctionInput lhs; + Circuit::FunctionInput rhs; + Circuit::Witness output; + + friend bool operator==(const BigIntAdd&, const BigIntAdd&); + std::vector bincodeSerialize() const; + static BigIntAdd bincodeDeserialize(std::vector); + }; + + struct BigIntNeg { + Circuit::FunctionInput lhs; + Circuit::FunctionInput rhs; + Circuit::Witness output; + + friend bool operator==(const BigIntNeg&, const BigIntNeg&); + std::vector bincodeSerialize() const; + static BigIntNeg bincodeDeserialize(std::vector); + }; + + struct BigIntMul { + Circuit::FunctionInput lhs; + Circuit::FunctionInput rhs; + Circuit::Witness output; + + friend bool operator==(const BigIntMul&, const BigIntMul&); + std::vector bincodeSerialize() const; + static BigIntMul bincodeDeserialize(std::vector); + }; + + struct BigIntDiv { + Circuit::FunctionInput lhs; + Circuit::FunctionInput rhs; + Circuit::Witness output; + + friend bool operator==(const BigIntDiv&, const BigIntDiv&); + std::vector bincodeSerialize() const; + static BigIntDiv bincodeDeserialize(std::vector); + }; + + struct BigIntFromLeBytes { + std::vector inputs; + std::vector modulus; + Circuit::Witness output; + + friend bool operator==(const BigIntFromLeBytes&, const BigIntFromLeBytes&); + std::vector bincodeSerialize() const; + static BigIntFromLeBytes bincodeDeserialize(std::vector); + }; + + struct BigIntToLeBytes { + Circuit::FunctionInput input; + std::vector outputs; + + friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); + std::vector bincodeSerialize() const; + static BigIntToLeBytes bincodeDeserialize(std::vector); + }; + + std::variant value; friend bool operator==(const BlackBoxFuncCall&, const BlackBoxFuncCall&); std::vector bincodeSerialize() const; @@ -543,7 +602,66 @@ namespace Circuit { static EmbeddedCurveDouble bincodeDeserialize(std::vector); }; - std::variant value; + struct BigIntAdd { + Circuit::RegisterIndex lhs; + Circuit::RegisterIndex rhs; + Circuit::RegisterIndex output; + + friend bool operator==(const BigIntAdd&, const BigIntAdd&); + std::vector bincodeSerialize() const; + static BigIntAdd bincodeDeserialize(std::vector); + }; + + struct BigIntNeg { + Circuit::RegisterIndex lhs; + Circuit::RegisterIndex rhs; + Circuit::RegisterIndex output; + + friend bool operator==(const BigIntNeg&, const BigIntNeg&); + std::vector bincodeSerialize() const; + static BigIntNeg bincodeDeserialize(std::vector); + }; + + struct BigIntMul { + Circuit::RegisterIndex lhs; + Circuit::RegisterIndex rhs; + Circuit::RegisterIndex output; + + friend bool operator==(const BigIntMul&, const BigIntMul&); + std::vector bincodeSerialize() const; + static BigIntMul bincodeDeserialize(std::vector); + }; + + struct BigIntDiv { + Circuit::RegisterIndex lhs; + Circuit::RegisterIndex rhs; + Circuit::RegisterIndex output; + + friend bool operator==(const BigIntDiv&, const BigIntDiv&); + std::vector bincodeSerialize() const; + static BigIntDiv bincodeDeserialize(std::vector); + }; + + struct BigIntFromLeBytes { + Circuit::HeapVector inputs; + Circuit::HeapVector modulus; + Circuit::RegisterIndex output; + + friend bool operator==(const BigIntFromLeBytes&, const BigIntFromLeBytes&); + std::vector bincodeSerialize() const; + static BigIntFromLeBytes bincodeDeserialize(std::vector); + }; + + struct BigIntToLeBytes { + Circuit::RegisterIndex input; + Circuit::HeapVector output; + + friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); + std::vector bincodeSerialize() const; + static BigIntToLeBytes bincodeDeserialize(std::vector); + }; + + std::variant value; friend bool operator==(const BlackBoxOp&, const BlackBoxOp&); std::vector bincodeSerialize() const; @@ -2469,6 +2587,267 @@ Circuit::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable BlackBoxFuncCall::BigIntAdd::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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::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 +Circuit::BlackBoxFuncCall::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::BigIntAdd obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + + inline bool operator==(const BlackBoxFuncCall::BigIntNeg &lhs, const BlackBoxFuncCall::BigIntNeg &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::BigIntNeg::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BlackBoxFuncCall::BigIntNeg BlackBoxFuncCall::BigIntNeg::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntNeg &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.lhs, serializer); + serde::Serializable::serialize(obj.rhs, serializer); + serde::Serializable::serialize(obj.output, serializer); +} + +template <> +template +Circuit::BlackBoxFuncCall::BigIntNeg serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::BigIntNeg obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + + 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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::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 +Circuit::BlackBoxFuncCall::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::BigIntMul obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + + 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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::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 +Circuit::BlackBoxFuncCall::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::BigIntDiv obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + + 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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::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 +Circuit::BlackBoxFuncCall::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::BigIntFromLeBytes obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.modulus = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + + 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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntToLeBytes &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.input, serializer); + serde::Serializable::serialize(obj.outputs, serializer); +} + +template <> +template +Circuit::BlackBoxFuncCall::BigIntToLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::BigIntToLeBytes obj; + obj.input = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + return obj; +} + namespace Circuit { inline bool operator==(const BlackBoxOp &lhs, const BlackBoxOp &rhs) { @@ -3092,6 +3471,267 @@ Circuit::BlackBoxOp::EmbeddedCurveDouble serde::Deserializable 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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::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 +Circuit::BlackBoxOp::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxOp::BigIntAdd obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + + inline bool operator==(const BlackBoxOp::BigIntNeg &lhs, const BlackBoxOp::BigIntNeg &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::BigIntNeg::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BlackBoxOp::BigIntNeg BlackBoxOp::BigIntNeg::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntNeg &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.lhs, serializer); + serde::Serializable::serialize(obj.rhs, serializer); + serde::Serializable::serialize(obj.output, serializer); +} + +template <> +template +Circuit::BlackBoxOp::BigIntNeg serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxOp::BigIntNeg obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + + 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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::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 +Circuit::BlackBoxOp::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxOp::BigIntMul obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + + 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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::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 +Circuit::BlackBoxOp::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxOp::BigIntDiv obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + + 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; } + return true; + } + + inline std::vector BlackBoxOp::BigIntFromLeBytes::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BlackBoxOp::BigIntFromLeBytes BlackBoxOp::BigIntFromLeBytes::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntFromLeBytes &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.modulus, serializer); + serde::Serializable::serialize(obj.output, serializer); +} + +template <> +template +Circuit::BlackBoxOp::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxOp::BigIntFromLeBytes obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.modulus = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + + 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; } + return true; + } + + inline std::vector BlackBoxOp::BigIntToLeBytes::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BlackBoxOp::BigIntToLeBytes BlackBoxOp::BigIntToLeBytes::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Circuit + +template <> +template +void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntToLeBytes &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.input, serializer); + serde::Serializable::serialize(obj.output, serializer); +} + +template <> +template +Circuit::BlackBoxOp::BigIntToLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxOp::BigIntToLeBytes obj; + obj.input = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + namespace Circuit { inline bool operator==(const BlockId &lhs, const BlockId &rhs) { diff --git a/noir/acvm-repo/acir/src/circuit/black_box_functions.rs b/noir/acvm-repo/acir/src/circuit/black_box_functions.rs index d1f5560313b..41b8923a8c9 100644 --- a/noir/acvm-repo/acir/src/circuit/black_box_functions.rs +++ b/noir/acvm-repo/acir/src/circuit/black_box_functions.rs @@ -49,6 +49,18 @@ pub enum BlackBoxFunc { EmbeddedCurveAdd, /// Point doubling over the embedded curve on which [`FieldElement`][acir_field::FieldElement] is defined. EmbeddedCurveDouble, + /// BigInt addition + BigIntAdd, + /// BigInt subtraction + BigIntNeg, + /// BigInt multiplication + BigIntMul, + /// BigInt division + BigIntDiv, + /// BigInt from le bytes + BigIntFromLeBytes, + /// BigInt to le bytes + BigIntToLeBytes, } impl std::fmt::Display for BlackBoxFunc { @@ -77,8 +89,15 @@ impl BlackBoxFunc { BlackBoxFunc::Keccakf1600 => "keccakf1600", BlackBoxFunc::RecursiveAggregation => "recursive_aggregation", BlackBoxFunc::EcdsaSecp256r1 => "ecdsa_secp256r1", + BlackBoxFunc::BigIntAdd => "bigint_add", + BlackBoxFunc::BigIntNeg => "bigint_neg", + BlackBoxFunc::BigIntMul => "bigint_mul", + BlackBoxFunc::BigIntDiv => "bigint_div", + BlackBoxFunc::BigIntFromLeBytes => "bigint_from_le_bytes", + BlackBoxFunc::BigIntToLeBytes => "bigint_to_le_bytes", } } + pub fn lookup(op_name: &str) -> Option { match op_name { "sha256" => Some(BlackBoxFunc::SHA256), @@ -98,6 +117,12 @@ impl BlackBoxFunc { "keccak256" => Some(BlackBoxFunc::Keccak256), "keccakf1600" => Some(BlackBoxFunc::Keccakf1600), "recursive_aggregation" => Some(BlackBoxFunc::RecursiveAggregation), + "bigint_add" => Some(BlackBoxFunc::BigIntAdd), + "bigint_neg" => Some(BlackBoxFunc::BigIntNeg), + "bigint_mul" => Some(BlackBoxFunc::BigIntMul), + "bigint_div" => Some(BlackBoxFunc::BigIntDiv), + "bigint_from_le_bytes" => Some(BlackBoxFunc::BigIntFromLeBytes), + "bigint_to_le_bytes" => Some(BlackBoxFunc::BigIntToLeBytes), _ => None, } } diff --git a/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs b/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs index 7ee4e2498a5..7eb95de6b19 100644 --- a/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs +++ b/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs @@ -120,6 +120,35 @@ pub enum BlackBoxFuncCall { /// key provided to the circuit matches the key produced by the circuit creator key_hash: FunctionInput, }, + BigIntAdd { + lhs: FunctionInput, + rhs: FunctionInput, + output: Witness, + }, + BigIntNeg { + lhs: FunctionInput, + rhs: FunctionInput, + output: Witness, + }, + BigIntMul { + lhs: FunctionInput, + rhs: FunctionInput, + output: Witness, + }, + BigIntDiv { + lhs: FunctionInput, + rhs: FunctionInput, + output: Witness, + }, + BigIntFromLeBytes { + inputs: Vec, + modulus: Vec, + output: Witness, + }, + BigIntToLeBytes { + input: FunctionInput, + outputs: Vec, + }, } impl BlackBoxFuncCall { @@ -143,6 +172,12 @@ impl BlackBoxFuncCall { BlackBoxFuncCall::Keccak256VariableLength { .. } => BlackBoxFunc::Keccak256, BlackBoxFuncCall::Keccakf1600 { .. } => BlackBoxFunc::Keccakf1600, BlackBoxFuncCall::RecursiveAggregation { .. } => BlackBoxFunc::RecursiveAggregation, + BlackBoxFuncCall::BigIntAdd { .. } => BlackBoxFunc::BigIntAdd, + BlackBoxFuncCall::BigIntNeg { .. } => BlackBoxFunc::BigIntNeg, + BlackBoxFuncCall::BigIntMul { .. } => BlackBoxFunc::BigIntMul, + BlackBoxFuncCall::BigIntDiv { .. } => BlackBoxFunc::BigIntDiv, + BlackBoxFuncCall::BigIntFromLeBytes { .. } => BlackBoxFunc::BigIntFromLeBytes, + &BlackBoxFuncCall::BigIntToLeBytes { .. } => BlackBoxFunc::BigIntToLeBytes, } } @@ -158,8 +193,15 @@ impl BlackBoxFuncCall { | BlackBoxFuncCall::Keccak256 { inputs, .. } | BlackBoxFuncCall::Keccakf1600 { inputs, .. } | BlackBoxFuncCall::PedersenCommitment { inputs, .. } - | BlackBoxFuncCall::PedersenHash { inputs, .. } => inputs.to_vec(), - BlackBoxFuncCall::AND { lhs, rhs, .. } | BlackBoxFuncCall::XOR { lhs, rhs, .. } => { + | BlackBoxFuncCall::PedersenHash { inputs, .. } + | BlackBoxFuncCall::BigIntFromLeBytes { inputs, .. } => inputs.to_vec(), + BlackBoxFuncCall::BigIntToLeBytes { input, .. } => vec![*input], + BlackBoxFuncCall::AND { lhs, rhs, .. } + | BlackBoxFuncCall::XOR { lhs, rhs, .. } + | BlackBoxFuncCall::BigIntAdd { lhs, rhs, .. } + | BlackBoxFuncCall::BigIntNeg { lhs, rhs, .. } + | BlackBoxFuncCall::BigIntMul { lhs, rhs, .. } + | BlackBoxFuncCall::BigIntDiv { lhs, rhs, .. } => { vec![*lhs, *rhs] } BlackBoxFuncCall::FixedBaseScalarMul { low, high, .. } => vec![*low, *high], @@ -249,13 +291,19 @@ impl BlackBoxFuncCall { | BlackBoxFuncCall::Blake2s { outputs, .. } | BlackBoxFuncCall::Blake3 { outputs, .. } | BlackBoxFuncCall::Keccak256 { outputs, .. } - | BlackBoxFuncCall::Keccakf1600 { outputs, .. } => outputs.to_vec(), + | BlackBoxFuncCall::Keccakf1600 { outputs, .. } + | BlackBoxFuncCall::Keccak256VariableLength { outputs, .. } => outputs.to_vec(), BlackBoxFuncCall::AND { output, .. } | BlackBoxFuncCall::XOR { output, .. } | BlackBoxFuncCall::SchnorrVerify { output, .. } | BlackBoxFuncCall::EcdsaSecp256k1 { output, .. } | BlackBoxFuncCall::PedersenHash { output, .. } - | BlackBoxFuncCall::EcdsaSecp256r1 { output, .. } => vec![*output], + | BlackBoxFuncCall::EcdsaSecp256r1 { output, .. } + | BlackBoxFuncCall::BigIntAdd { output, .. } + | BlackBoxFuncCall::BigIntNeg { output, .. } + | BlackBoxFuncCall::BigIntMul { output, .. } + | BlackBoxFuncCall::BigIntDiv { output, .. } + | BlackBoxFuncCall::BigIntFromLeBytes { output, .. } => vec![*output], BlackBoxFuncCall::FixedBaseScalarMul { outputs, .. } | BlackBoxFuncCall::PedersenCommitment { outputs, .. } | BlackBoxFuncCall::EmbeddedCurveAdd { outputs, .. } @@ -263,7 +311,7 @@ impl BlackBoxFuncCall { BlackBoxFuncCall::RANGE { .. } | BlackBoxFuncCall::RecursiveAggregation { .. } => { vec![] } - BlackBoxFuncCall::Keccak256VariableLength { outputs, .. } => outputs.to_vec(), + BlackBoxFuncCall::BigIntToLeBytes { outputs, .. } => outputs.to_vec(), } } } diff --git a/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs b/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs index 306ea1b7c12..74ef858455b 100644 --- a/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -101,7 +101,14 @@ pub(super) fn transform_internal( Opcode::BlackBoxFuncCall(ref func) => { match func { acir::circuit::opcodes::BlackBoxFuncCall::AND { output, .. } - | acir::circuit::opcodes::BlackBoxFuncCall::XOR { output, .. } => { + | acir::circuit::opcodes::BlackBoxFuncCall::XOR { output, .. } + | acir::circuit::opcodes::BlackBoxFuncCall::BigIntAdd { output, .. } + | acir::circuit::opcodes::BlackBoxFuncCall::BigIntNeg { output, .. } + | acir::circuit::opcodes::BlackBoxFuncCall::BigIntMul { output, .. } + | acir::circuit::opcodes::BlackBoxFuncCall::BigIntDiv { output, .. } + | acir::circuit::opcodes::BlackBoxFuncCall::BigIntFromLeBytes { + output, .. + } => { transformer.mark_solvable(*output); } acir::circuit::opcodes::BlackBoxFuncCall::RANGE { .. } @@ -114,7 +121,10 @@ pub(super) fn transform_internal( } | acir::circuit::opcodes::BlackBoxFuncCall::Keccakf1600 { outputs, .. } | acir::circuit::opcodes::BlackBoxFuncCall::Blake2s { outputs, .. } - | acir::circuit::opcodes::BlackBoxFuncCall::Blake3 { outputs, .. } => { + | acir::circuit::opcodes::BlackBoxFuncCall::Blake3 { outputs, .. } + | acir::circuit::opcodes::BlackBoxFuncCall::BigIntToLeBytes { + outputs, .. + } => { for witness in outputs { transformer.mark_solvable(*witness); } diff --git a/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs b/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs index 5eea234885c..a56b24b86f3 100644 --- a/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs +++ b/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs @@ -185,5 +185,11 @@ pub(crate) fn solve( } // Recursive aggregation will be entirely handled by the backend and is not solved by the ACVM BlackBoxFuncCall::RecursiveAggregation { .. } => Ok(()), + BlackBoxFuncCall::BigIntAdd { .. } => todo!(), + BlackBoxFuncCall::BigIntNeg { .. } => todo!(), + BlackBoxFuncCall::BigIntMul { .. } => todo!(), + BlackBoxFuncCall::BigIntDiv { .. } => todo!(), + BlackBoxFuncCall::BigIntFromLeBytes { .. } => todo!(), + BlackBoxFuncCall::BigIntToLeBytes { .. } => todo!(), } } diff --git a/noir/acvm-repo/brillig/src/black_box.rs b/noir/acvm-repo/brillig/src/black_box.rs index c007e78b785..5893758ce9e 100644 --- a/noir/acvm-repo/brillig/src/black_box.rs +++ b/noir/acvm-repo/brillig/src/black_box.rs @@ -6,15 +6,30 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub enum BlackBoxOp { /// Calculates the SHA256 hash of the inputs. - Sha256 { message: HeapVector, output: HeapArray }, + Sha256 { + message: HeapVector, + output: HeapArray, + }, /// Calculates the Blake2s hash of the inputs. - Blake2s { message: HeapVector, output: HeapArray }, + Blake2s { + message: HeapVector, + output: HeapArray, + }, /// Calculates the Blake3 hash of the inputs. - Blake3 { message: HeapVector, output: HeapArray }, + Blake3 { + message: HeapVector, + output: HeapArray, + }, /// Calculates the Keccak256 hash of the inputs. - Keccak256 { message: HeapVector, output: HeapArray }, + Keccak256 { + message: HeapVector, + output: HeapArray, + }, /// Keccak Permutation function of 1600 width - Keccakf1600 { message: HeapVector, output: HeapArray }, + Keccakf1600 { + message: HeapVector, + output: HeapArray, + }, /// Verifies a ECDSA signature over the secp256k1 curve. EcdsaSecp256k1 { hashed_msg: HeapVector, @@ -40,11 +55,23 @@ pub enum BlackBoxOp { result: RegisterIndex, }, /// Calculates a Pedersen commitment to the inputs. - PedersenCommitment { inputs: HeapVector, domain_separator: RegisterIndex, output: HeapArray }, + PedersenCommitment { + inputs: HeapVector, + domain_separator: RegisterIndex, + output: HeapArray, + }, /// Calculates a Pedersen hash to the inputs. - PedersenHash { inputs: HeapVector, domain_separator: RegisterIndex, output: RegisterIndex }, + PedersenHash { + inputs: HeapVector, + domain_separator: RegisterIndex, + output: RegisterIndex, + }, /// Performs scalar multiplication over the embedded curve. - FixedBaseScalarMul { low: RegisterIndex, high: RegisterIndex, result: HeapArray }, + FixedBaseScalarMul { + low: RegisterIndex, + high: RegisterIndex, + result: HeapArray, + }, /// Performs addition over the embedded curve. EmbeddedCurveAdd { input1_x: RegisterIndex, @@ -54,5 +81,39 @@ pub enum BlackBoxOp { result: HeapArray, }, /// Performs point doubling over the embedded curve. - EmbeddedCurveDouble { input1_x: RegisterIndex, input1_y: RegisterIndex, result: HeapArray }, + EmbeddedCurveDouble { + input1_x: RegisterIndex, + input1_y: RegisterIndex, + result: HeapArray, + }, + + BigIntAdd { + lhs: RegisterIndex, + rhs: RegisterIndex, + output: RegisterIndex, + }, + BigIntNeg { + lhs: RegisterIndex, + rhs: RegisterIndex, + output: RegisterIndex, + }, + BigIntMul { + lhs: RegisterIndex, + rhs: RegisterIndex, + output: RegisterIndex, + }, + BigIntDiv { + lhs: RegisterIndex, + rhs: RegisterIndex, + output: RegisterIndex, + }, + BigIntFromLeBytes { + inputs: HeapVector, + modulus: HeapVector, + output: RegisterIndex, + }, + BigIntToLeBytes { + input: RegisterIndex, + output: HeapVector, + }, } diff --git a/noir/acvm-repo/brillig_vm/src/black_box.rs b/noir/acvm-repo/brillig_vm/src/black_box.rs index 463038509e1..edbebb61ece 100644 --- a/noir/acvm-repo/brillig_vm/src/black_box.rs +++ b/noir/acvm-repo/brillig_vm/src/black_box.rs @@ -200,6 +200,12 @@ pub(crate) fn evaluate_black_box( registers.set(*output, hash.into()); Ok(()) } + BlackBoxOp::BigIntAdd { .. } => todo!(), + BlackBoxOp::BigIntNeg { .. } => todo!(), + BlackBoxOp::BigIntMul { .. } => todo!(), + BlackBoxOp::BigIntDiv { .. } => todo!(), + BlackBoxOp::BigIntFromLeBytes { .. } => todo!(), + BlackBoxOp::BigIntToLeBytes { .. } => todo!(), } } @@ -218,6 +224,12 @@ fn black_box_function_from_op(op: &BlackBoxOp) -> BlackBoxFunc { BlackBoxOp::FixedBaseScalarMul { .. } => BlackBoxFunc::FixedBaseScalarMul, BlackBoxOp::EmbeddedCurveAdd { .. } => BlackBoxFunc::EmbeddedCurveAdd, BlackBoxOp::EmbeddedCurveDouble { .. } => BlackBoxFunc::EmbeddedCurveDouble, + BlackBoxOp::BigIntAdd { .. } => BlackBoxFunc::BigIntAdd, + BlackBoxOp::BigIntNeg { .. } => BlackBoxFunc::BigIntNeg, + BlackBoxOp::BigIntMul { .. } => BlackBoxFunc::BigIntMul, + BlackBoxOp::BigIntDiv { .. } => BlackBoxFunc::BigIntDiv, + BlackBoxOp::BigIntFromLeBytes { .. } => BlackBoxFunc::BigIntFromLeBytes, + BlackBoxOp::BigIntToLeBytes { .. } => BlackBoxFunc::BigIntToLeBytes, } } diff --git a/noir/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs b/noir/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs index c081806f4a7..c7b6f39279b 100644 --- a/noir/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs +++ b/noir/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs @@ -244,6 +244,107 @@ pub(crate) fn convert_black_box_call( BlackBoxFunc::RecursiveAggregation => unimplemented!( "ICE: `BlackBoxFunc::RecursiveAggregation` is not implemented by the Brillig VM" ), + BlackBoxFunc::BigIntAdd => { + if let ( + [BrilligVariable::Simple(lhs), BrilligVariable::Simple(rhs)], + [BrilligVariable::Simple(output)], + ) = (function_arguments, function_results) + { + brillig_context.black_box_op_instruction(BlackBoxOp::BigIntAdd { + lhs: *lhs, + rhs: *rhs, + output: *output, + }); + } else { + unreachable!( + "ICE: EmbeddedCurveAdd expects two register arguments and one array result" + ) + } + } + BlackBoxFunc::BigIntNeg => { + if let ( + [BrilligVariable::Simple(lhs), BrilligVariable::Simple(rhs)], + [BrilligVariable::Simple(output)], + ) = (function_arguments, function_results) + { + brillig_context.black_box_op_instruction(BlackBoxOp::BigIntNeg { + lhs: *lhs, + rhs: *rhs, + output: *output, + }); + } else { + unreachable!( + "ICE: EmbeddedCurveAdd expects two register arguments and one array result" + ) + } + } + BlackBoxFunc::BigIntMul => { + if let ( + [BrilligVariable::Simple(lhs), BrilligVariable::Simple(rhs)], + [BrilligVariable::Simple(output)], + ) = (function_arguments, function_results) + { + brillig_context.black_box_op_instruction(BlackBoxOp::BigIntMul { + lhs: *lhs, + rhs: *rhs, + output: *output, + }); + } else { + unreachable!( + "ICE: EmbeddedCurveAdd expects two register arguments and one array result" + ) + } + } + BlackBoxFunc::BigIntDiv => { + if let ( + [BrilligVariable::Simple(lhs), BrilligVariable::Simple(rhs)], + [BrilligVariable::Simple(output)], + ) = (function_arguments, function_results) + { + brillig_context.black_box_op_instruction(BlackBoxOp::BigIntDiv { + lhs: *lhs, + rhs: *rhs, + output: *output, + }); + } else { + unreachable!( + "ICE: EmbeddedCurveAdd expects two register arguments and one array result" + ) + } + } + BlackBoxFunc::BigIntFromLeBytes => { + if let ([inputs, modulus], [BrilligVariable::Simple(output)]) = + (function_arguments, function_results) + { + let inputs_vector = convert_array_or_vector(brillig_context, inputs, bb_func); + let modulus_vector = convert_array_or_vector(brillig_context, modulus, bb_func); + brillig_context.black_box_op_instruction(BlackBoxOp::BigIntFromLeBytes { + inputs: inputs_vector.to_heap_vector(), + modulus: modulus_vector.to_heap_vector(), + output: *output, + }); + } else { + unreachable!( + "ICE: EmbeddedCurveAdd expects two register arguments and one array result" + ) + } + } + BlackBoxFunc::BigIntToLeBytes => { + if let ( + [BrilligVariable::Simple(input)], + [BrilligVariable::BrilligVector(result_vector)], + ) = (function_arguments, function_results) + { + brillig_context.black_box_op_instruction(BlackBoxOp::BigIntToLeBytes { + input: *input, + output: result_vector.to_heap_vector(), + }); + } else { + unreachable!( + "ICE: EmbeddedCurveAdd expects two register arguments and one array result" + ) + } + } } } diff --git a/noir/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs b/noir/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs index dc8c6b6694c..5709b0a1aa2 100644 --- a/noir/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs +++ b/noir/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs @@ -457,6 +457,59 @@ impl DebugShow { result ); } + BlackBoxOp::BigIntAdd { lhs, rhs, output } => { + debug_println!( + self.enable_debug_trace, + " BIGINT_ADD {} {} -> {}", + lhs, + rhs, + output + ); + } + BlackBoxOp::BigIntNeg { 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 + ); + } } } diff --git a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index 623810d1bfe..b7fdb17bef0 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -244,6 +244,34 @@ impl GeneratedAcir { public_inputs: inputs[2].clone(), key_hash: inputs[3][0], }, + BlackBoxFunc::BigIntAdd => BlackBoxFuncCall::BigIntAdd { + lhs: inputs[0][0], + rhs: inputs[1][0], + output: outputs[0], + }, + BlackBoxFunc::BigIntNeg => BlackBoxFuncCall::BigIntNeg { + lhs: inputs[0][0], + rhs: inputs[1][0], + output: outputs[0], + }, + BlackBoxFunc::BigIntMul => BlackBoxFuncCall::BigIntMul { + lhs: inputs[0][0], + rhs: inputs[1][0], + output: outputs[0], + }, + BlackBoxFunc::BigIntDiv => BlackBoxFuncCall::BigIntDiv { + lhs: inputs[0][0], + rhs: inputs[1][0], + output: outputs[0], + }, + BlackBoxFunc::BigIntFromLeBytes => BlackBoxFuncCall::BigIntFromLeBytes { + inputs: inputs[0].clone(), + modulus: inputs[1].clone(), + output: outputs[0], + }, + BlackBoxFunc::BigIntToLeBytes => { + BlackBoxFuncCall::BigIntToLeBytes { input: inputs[0][0], outputs } + } }; self.push_opcode(AcirOpcode::BlackBoxFuncCall(black_box_func_call)); @@ -566,6 +594,7 @@ fn black_box_func_expected_input_size(name: BlackBoxFunc) -> Option { match name { // Bitwise opcodes will take in 2 parameters BlackBoxFunc::AND | BlackBoxFunc::XOR => Some(2), + // All of the hash/cipher methods will take in a // variable number of inputs. BlackBoxFunc::Keccak256 @@ -586,15 +615,30 @@ fn black_box_func_expected_input_size(name: BlackBoxFunc) -> Option { BlackBoxFunc::SchnorrVerify | BlackBoxFunc::EcdsaSecp256k1 | BlackBoxFunc::EcdsaSecp256r1 => None, + // Inputs for fixed based scalar multiplication // is the low and high limbs of the scalar BlackBoxFunc::FixedBaseScalarMul => Some(2), + // Recursive aggregation has a variable number of inputs BlackBoxFunc::RecursiveAggregation => None, + // Addition over the embedded curve: input are coordinates (x1,y1) and (x2,y2) of the Grumpkin points BlackBoxFunc::EmbeddedCurveAdd => Some(4), + // Doubling over the embedded curve: input is (x,y) coordinate of the point. BlackBoxFunc::EmbeddedCurveDouble => Some(2), + + // Big integer operations take in 2 inputs + BlackBoxFunc::BigIntAdd + | BlackBoxFunc::BigIntNeg + | BlackBoxFunc::BigIntMul + | BlackBoxFunc::BigIntDiv => Some(2), + + // FromLeBytes takes a variable array of bytes as input + BlackBoxFunc::BigIntFromLeBytes => None, + // ToLeBytes takes a single big integer as input + BlackBoxFunc::BigIntToLeBytes => Some(1), } } @@ -605,28 +649,46 @@ fn black_box_expected_output_size(name: BlackBoxFunc) -> Option { // Bitwise opcodes will return 1 parameter which is the output // or the operation. BlackBoxFunc::AND | BlackBoxFunc::XOR => Some(1), + // 32 byte hash algorithms BlackBoxFunc::Keccak256 | BlackBoxFunc::SHA256 | BlackBoxFunc::Blake2s | BlackBoxFunc::Blake3 => Some(32), + BlackBoxFunc::Keccakf1600 => Some(25), + // Pedersen commitment returns a point BlackBoxFunc::PedersenCommitment => Some(2), + // Pedersen hash returns a field BlackBoxFunc::PedersenHash => Some(1), + // Can only apply a range constraint to one // witness at a time. BlackBoxFunc::RANGE => Some(0), + // Signature verification algorithms will return a boolean BlackBoxFunc::SchnorrVerify | BlackBoxFunc::EcdsaSecp256k1 | BlackBoxFunc::EcdsaSecp256r1 => Some(1), + // Output of operations over the embedded curve // will be 2 field elements representing the point. BlackBoxFunc::FixedBaseScalarMul | BlackBoxFunc::EmbeddedCurveAdd | BlackBoxFunc::EmbeddedCurveDouble => Some(2), + + // Big integer operations return a big integer + BlackBoxFunc::BigIntAdd + | BlackBoxFunc::BigIntNeg + | BlackBoxFunc::BigIntMul + | BlackBoxFunc::BigIntDiv + | BlackBoxFunc::BigIntFromLeBytes => Some(1), + + // ToLeBytes returns a variable array of bytes + BlackBoxFunc::BigIntToLeBytes => None, + // Recursive aggregation has a variable number of outputs BlackBoxFunc::RecursiveAggregation => None, } diff --git a/noir/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs b/noir/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs index b0ee8468bd8..dbfc58e7588 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs @@ -444,8 +444,13 @@ fn simplify_black_box_func( // Currently unsolvable here as we rely on an implementation in the backend. SimplifyResult::None } - - BlackBoxFunc::RecursiveAggregation => SimplifyResult::None, + BlackBoxFunc::BigIntAdd + | BlackBoxFunc::BigIntNeg + | BlackBoxFunc::BigIntMul + | BlackBoxFunc::BigIntDiv + | BlackBoxFunc::RecursiveAggregation + | BlackBoxFunc::BigIntFromLeBytes + | BlackBoxFunc::BigIntToLeBytes => SimplifyResult::None, BlackBoxFunc::AND => { unreachable!("ICE: `BlackBoxFunc::AND` calls should be transformed into a `BinaryOp`") From 6c4c4510b9bcc02e17f05b30a744f1a4c00c810b Mon Sep 17 00:00:00 2001 From: guipublic Date: Mon, 22 Jan 2024 10:39:52 +0000 Subject: [PATCH 2/9] Use id to identify bigints between Noir and BB --- .../dsl/acir_format/serde/acir.hpp | 30 +++++----- noir/acvm-repo/acir/codegen/acir.cpp | 30 +++++----- .../opcodes/black_box_function_call.rs | 58 +++++++++---------- .../acvm/src/compiler/transformers/mod.rs | 16 +++-- 4 files changed, 66 insertions(+), 68 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp index e568a7e5404..8e18e5bc043 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp @@ -207,9 +207,9 @@ struct BlackBoxFuncCall { }; struct BigIntAdd { - Circuit::FunctionInput lhs; - Circuit::FunctionInput rhs; - Circuit::Witness output; + uint32_t lhs; + uint32_t rhs; + uint32_t output; friend bool operator==(const BigIntAdd&, const BigIntAdd&); std::vector bincodeSerialize() const; @@ -217,9 +217,9 @@ struct BlackBoxFuncCall { }; struct BigIntNeg { - Circuit::FunctionInput lhs; - Circuit::FunctionInput rhs; - Circuit::Witness output; + uint32_t lhs; + uint32_t rhs; + uint32_t output; friend bool operator==(const BigIntNeg&, const BigIntNeg&); std::vector bincodeSerialize() const; @@ -227,9 +227,9 @@ struct BlackBoxFuncCall { }; struct BigIntMul { - Circuit::FunctionInput lhs; - Circuit::FunctionInput rhs; - Circuit::Witness output; + uint32_t lhs; + uint32_t rhs; + uint32_t output; friend bool operator==(const BigIntMul&, const BigIntMul&); std::vector bincodeSerialize() const; @@ -237,9 +237,9 @@ struct BlackBoxFuncCall { }; struct BigIntDiv { - Circuit::FunctionInput lhs; - Circuit::FunctionInput rhs; - Circuit::Witness output; + uint32_t lhs; + uint32_t rhs; + uint32_t output; friend bool operator==(const BigIntDiv&, const BigIntDiv&); std::vector bincodeSerialize() const; @@ -248,8 +248,8 @@ struct BlackBoxFuncCall { struct BigIntFromLeBytes { std::vector inputs; - std::vector modulus; - Circuit::Witness output; + std::vector modulus; + uint32_t output; friend bool operator==(const BigIntFromLeBytes&, const BigIntFromLeBytes&); std::vector bincodeSerialize() const; @@ -257,7 +257,7 @@ struct BlackBoxFuncCall { }; struct BigIntToLeBytes { - Circuit::FunctionInput input; + uint32_t input; std::vector outputs; friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); diff --git a/noir/acvm-repo/acir/codegen/acir.cpp b/noir/acvm-repo/acir/codegen/acir.cpp index 47675775910..07bcd5f9f97 100644 --- a/noir/acvm-repo/acir/codegen/acir.cpp +++ b/noir/acvm-repo/acir/codegen/acir.cpp @@ -207,9 +207,9 @@ namespace Circuit { }; struct BigIntAdd { - Circuit::FunctionInput lhs; - Circuit::FunctionInput rhs; - Circuit::Witness output; + uint32_t lhs; + uint32_t rhs; + uint32_t output; friend bool operator==(const BigIntAdd&, const BigIntAdd&); std::vector bincodeSerialize() const; @@ -217,9 +217,9 @@ namespace Circuit { }; struct BigIntNeg { - Circuit::FunctionInput lhs; - Circuit::FunctionInput rhs; - Circuit::Witness output; + uint32_t lhs; + uint32_t rhs; + uint32_t output; friend bool operator==(const BigIntNeg&, const BigIntNeg&); std::vector bincodeSerialize() const; @@ -227,9 +227,9 @@ namespace Circuit { }; struct BigIntMul { - Circuit::FunctionInput lhs; - Circuit::FunctionInput rhs; - Circuit::Witness output; + uint32_t lhs; + uint32_t rhs; + uint32_t output; friend bool operator==(const BigIntMul&, const BigIntMul&); std::vector bincodeSerialize() const; @@ -237,9 +237,9 @@ namespace Circuit { }; struct BigIntDiv { - Circuit::FunctionInput lhs; - Circuit::FunctionInput rhs; - Circuit::Witness output; + uint32_t lhs; + uint32_t rhs; + uint32_t output; friend bool operator==(const BigIntDiv&, const BigIntDiv&); std::vector bincodeSerialize() const; @@ -248,8 +248,8 @@ namespace Circuit { struct BigIntFromLeBytes { std::vector inputs; - std::vector modulus; - Circuit::Witness output; + std::vector modulus; + uint32_t output; friend bool operator==(const BigIntFromLeBytes&, const BigIntFromLeBytes&); std::vector bincodeSerialize() const; @@ -257,7 +257,7 @@ namespace Circuit { }; struct BigIntToLeBytes { - Circuit::FunctionInput input; + uint32_t input; std::vector outputs; friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); diff --git a/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs b/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs index 7eb95de6b19..1fdc0265377 100644 --- a/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs +++ b/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs @@ -121,32 +121,32 @@ pub enum BlackBoxFuncCall { key_hash: FunctionInput, }, BigIntAdd { - lhs: FunctionInput, - rhs: FunctionInput, - output: Witness, + lhs: u32, + rhs: u32, + output: u32, }, BigIntNeg { - lhs: FunctionInput, - rhs: FunctionInput, - output: Witness, + lhs: u32, + rhs: u32, + output: u32, }, BigIntMul { - lhs: FunctionInput, - rhs: FunctionInput, - output: Witness, + lhs: u32, + rhs: u32, + output: u32, }, BigIntDiv { - lhs: FunctionInput, - rhs: FunctionInput, - output: Witness, + lhs: u32, + rhs: u32, + output: u32, }, BigIntFromLeBytes { inputs: Vec, - modulus: Vec, - output: Witness, + modulus: Vec, + output: u32, }, BigIntToLeBytes { - input: FunctionInput, + input: u32, outputs: Vec, }, } @@ -195,15 +195,14 @@ impl BlackBoxFuncCall { | BlackBoxFuncCall::PedersenCommitment { inputs, .. } | BlackBoxFuncCall::PedersenHash { inputs, .. } | BlackBoxFuncCall::BigIntFromLeBytes { inputs, .. } => inputs.to_vec(), - BlackBoxFuncCall::BigIntToLeBytes { input, .. } => vec![*input], - BlackBoxFuncCall::AND { lhs, rhs, .. } - | BlackBoxFuncCall::XOR { lhs, rhs, .. } - | BlackBoxFuncCall::BigIntAdd { lhs, rhs, .. } - | BlackBoxFuncCall::BigIntNeg { lhs, rhs, .. } - | BlackBoxFuncCall::BigIntMul { lhs, rhs, .. } - | BlackBoxFuncCall::BigIntDiv { lhs, rhs, .. } => { + BlackBoxFuncCall::AND { lhs, rhs, .. } | BlackBoxFuncCall::XOR { lhs, rhs, .. } => { vec![*lhs, *rhs] } + BlackBoxFuncCall::BigIntAdd { .. } + | BlackBoxFuncCall::BigIntNeg { .. } + | BlackBoxFuncCall::BigIntMul { .. } + | BlackBoxFuncCall::BigIntDiv { .. } + | BlackBoxFuncCall::BigIntToLeBytes { .. } => Vec::new(), BlackBoxFuncCall::FixedBaseScalarMul { low, high, .. } => vec![*low, *high], BlackBoxFuncCall::EmbeddedCurveAdd { input1_x, input1_y, input2_x, input2_y, .. @@ -298,17 +297,18 @@ impl BlackBoxFuncCall { | BlackBoxFuncCall::SchnorrVerify { output, .. } | BlackBoxFuncCall::EcdsaSecp256k1 { output, .. } | BlackBoxFuncCall::PedersenHash { output, .. } - | BlackBoxFuncCall::EcdsaSecp256r1 { output, .. } - | BlackBoxFuncCall::BigIntAdd { output, .. } - | BlackBoxFuncCall::BigIntNeg { output, .. } - | BlackBoxFuncCall::BigIntMul { output, .. } - | BlackBoxFuncCall::BigIntDiv { output, .. } - | BlackBoxFuncCall::BigIntFromLeBytes { output, .. } => vec![*output], + | BlackBoxFuncCall::EcdsaSecp256r1 { output, .. } => vec![*output], BlackBoxFuncCall::FixedBaseScalarMul { outputs, .. } | BlackBoxFuncCall::PedersenCommitment { outputs, .. } | BlackBoxFuncCall::EmbeddedCurveAdd { outputs, .. } | BlackBoxFuncCall::EmbeddedCurveDouble { outputs, .. } => vec![outputs.0, outputs.1], - BlackBoxFuncCall::RANGE { .. } | BlackBoxFuncCall::RecursiveAggregation { .. } => { + BlackBoxFuncCall::RANGE { .. } + | BlackBoxFuncCall::RecursiveAggregation { .. } + | BlackBoxFuncCall::BigIntFromLeBytes { .. } + | BlackBoxFuncCall::BigIntAdd { .. } + | BlackBoxFuncCall::BigIntNeg { .. } + | BlackBoxFuncCall::BigIntMul { .. } + | BlackBoxFuncCall::BigIntDiv { .. } => { vec![] } BlackBoxFuncCall::BigIntToLeBytes { outputs, .. } => outputs.to_vec(), diff --git a/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs b/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs index 74ef858455b..effe1128d36 100644 --- a/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -101,18 +101,16 @@ pub(super) fn transform_internal( Opcode::BlackBoxFuncCall(ref func) => { match func { acir::circuit::opcodes::BlackBoxFuncCall::AND { output, .. } - | acir::circuit::opcodes::BlackBoxFuncCall::XOR { output, .. } - | acir::circuit::opcodes::BlackBoxFuncCall::BigIntAdd { output, .. } - | acir::circuit::opcodes::BlackBoxFuncCall::BigIntNeg { output, .. } - | acir::circuit::opcodes::BlackBoxFuncCall::BigIntMul { output, .. } - | acir::circuit::opcodes::BlackBoxFuncCall::BigIntDiv { output, .. } - | acir::circuit::opcodes::BlackBoxFuncCall::BigIntFromLeBytes { - output, .. - } => { + | acir::circuit::opcodes::BlackBoxFuncCall::XOR { output, .. } => { transformer.mark_solvable(*output); } acir::circuit::opcodes::BlackBoxFuncCall::RANGE { .. } - | acir::circuit::opcodes::BlackBoxFuncCall::RecursiveAggregation { .. } => (), + | acir::circuit::opcodes::BlackBoxFuncCall::RecursiveAggregation { .. } + | acir::circuit::opcodes::BlackBoxFuncCall::BigIntFromLeBytes { .. } + | acir::circuit::opcodes::BlackBoxFuncCall::BigIntAdd { .. } + | acir::circuit::opcodes::BlackBoxFuncCall::BigIntNeg { .. } + | acir::circuit::opcodes::BlackBoxFuncCall::BigIntMul { .. } + | acir::circuit::opcodes::BlackBoxFuncCall::BigIntDiv { .. } => (), acir::circuit::opcodes::BlackBoxFuncCall::SHA256 { outputs, .. } | acir::circuit::opcodes::BlackBoxFuncCall::Keccak256 { outputs, .. } | acir::circuit::opcodes::BlackBoxFuncCall::Keccak256VariableLength { From d7803df4f2006f006b62406bd5c11490f462257d Mon Sep 17 00:00:00 2001 From: guipublic Date: Mon, 22 Jan 2024 11:48:41 +0000 Subject: [PATCH 3/9] fix build --- .../ssa/acir_gen/acir_ir/generated_acir.rs | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index 75d823600e4..4572cf1dd08 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -252,32 +252,32 @@ impl GeneratedAcir { key_hash: inputs[3][0], }, BlackBoxFunc::BigIntAdd => BlackBoxFuncCall::BigIntAdd { - lhs: inputs[0][0], - rhs: inputs[1][0], - output: outputs[0], + lhs: constants[0].to_u128() as u32, + rhs: constants[1].to_u128() as u32, + output: constants[2].to_u128() as u32, }, BlackBoxFunc::BigIntNeg => BlackBoxFuncCall::BigIntNeg { - lhs: inputs[0][0], - rhs: inputs[1][0], - output: outputs[0], + lhs: constants[0].to_u128() as u32, + rhs: constants[1].to_u128() as u32, + output: constants[2].to_u128() as u32, }, BlackBoxFunc::BigIntMul => BlackBoxFuncCall::BigIntMul { - lhs: inputs[0][0], - rhs: inputs[1][0], - output: outputs[0], + lhs: constants[0].to_u128() as u32, + rhs: constants[1].to_u128() as u32, + output: constants[2].to_u128() as u32, }, BlackBoxFunc::BigIntDiv => BlackBoxFuncCall::BigIntDiv { - lhs: inputs[0][0], - rhs: inputs[1][0], - output: outputs[0], + lhs: constants[0].to_u128() as u32, + rhs: constants[1].to_u128() as u32, + output: constants[2].to_u128() as u32, }, BlackBoxFunc::BigIntFromLeBytes => BlackBoxFuncCall::BigIntFromLeBytes { inputs: inputs[0].clone(), - modulus: inputs[1].clone(), - output: outputs[0], + modulus: vecmap(constants, |c| c.to_u128() as u8), + output: todo!(), }, BlackBoxFunc::BigIntToLeBytes => { - BlackBoxFuncCall::BigIntToLeBytes { input: inputs[0][0], outputs } + BlackBoxFuncCall::BigIntToLeBytes { input: constants[0].to_u128() as u32, outputs } } }; From 50939d0c313c687799a97a818cbeb50857f3b17c Mon Sep 17 00:00:00 2001 From: guipublic <47281315+guipublic@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:28:18 +0100 Subject: [PATCH 4/9] chore: add unit test for BB big integer opcode implementation (#4177) The unit test is just creating big int constraints and should be updated when the constraints are implemented. --- .../dsl/acir_format/acir_format.cpp | 8 ++ .../dsl/acir_format/acir_format.hpp | 7 +- .../dsl/acir_format/acir_format.test.cpp | 12 +++ .../acir_format/acir_to_constraint_buf.hpp | 35 ++++++++ .../dsl/acir_format/bigint_constraint.cpp | 33 +++++++ .../dsl/acir_format/bigint_constraint.hpp | 35 ++++++++ .../acir_format/bigint_constraint.test.cpp | 88 +++++++++++++++++++ .../dsl/acir_format/block_constraint.test.cpp | 2 + .../dsl/acir_format/ecdsa_secp256k1.test.cpp | 6 ++ .../dsl/acir_format/ecdsa_secp256r1.test.cpp | 8 ++ .../acir_format/recursion_constraint.test.cpp | 4 + 11 files changed, 237 insertions(+), 1 deletion(-) create mode 100644 barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp create mode 100644 barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp create mode 100644 barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index 7299d359bc3..8d9900d434d 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -94,6 +94,14 @@ void build_constraints(Builder& builder, acir_format const& constraint_system, b create_block_constraints(builder, constraint, has_valid_witness_assignments); } + // Add big_int constraints + for (const auto& constraint : constraint_system.bigint_operations) { + create_bigint_operations_constraint(builder, constraint); + } + for (const auto& constraint : constraint_system.bigint_from_le_bytes_constraints) { + create_bigint_from_le_bytes_constraint(builder, constraint); + } + // TODO(https://github.com/AztecProtocol/barretenberg/issues/817): disable these for UGH for now since we're not yet // dealing with proper recursion if constexpr (IsGoblinBuilder) { diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp index 1cd81b2edbb..dbc4ce25e49 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp @@ -1,6 +1,7 @@ #pragma once #include "barretenberg/common/slab_allocator.hpp" #include "barretenberg/serialize/msgpack.hpp" +#include "bigint_constraint.hpp" #include "blake2s_constraint.hpp" #include "blake3_constraint.hpp" #include "block_constraint.hpp" @@ -41,6 +42,8 @@ struct acir_format { std::vector ec_add_constraints; std::vector ec_double_constraints; std::vector recursion_constraints; + std::vector bigint_from_le_bytes_constraints; + std::vector bigint_operations; // A standard plonk arithmetic constraint, as defined in the poly_triple struct, consists of selector values // for q_M,q_L,q_R,q_O,q_C and indices of three variables taking the role of left, right and output wire @@ -69,7 +72,9 @@ struct acir_format { fixed_base_scalar_mul_constraints, recursion_constraints, constraints, - block_constraints); + block_constraints, + bigint_from_le_bytes_constraints, + bigint_operations); friend bool operator==(acir_format const& lhs, acir_format const& rhs) = default; }; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp index 7aa0a0364ff..58d2cf65739 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp @@ -47,6 +47,8 @@ TEST_F(AcirFormatTests, TestASingleConstraintNoPubInputs) .ec_add_constraints = {}, .ec_double_constraints = {}, .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, .constraints = { constraint }, .block_constraints = {}, }; @@ -158,6 +160,8 @@ TEST_F(AcirFormatTests, TestLogicGateFromNoirCircuit) .ec_add_constraints = {}, .ec_double_constraints = {}, .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, .constraints = { expr_a, expr_b, expr_c, expr_d }, .block_constraints = {} }; @@ -221,6 +225,8 @@ TEST_F(AcirFormatTests, TestSchnorrVerifyPass) .ec_add_constraints = {}, .ec_double_constraints = {}, .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, .constraints = { poly_triple{ .a = schnorr_constraint.result, .b = schnorr_constraint.result, @@ -312,6 +318,8 @@ TEST_F(AcirFormatTests, TestSchnorrVerifySmallRange) .ec_add_constraints = {}, .ec_double_constraints = {}, .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, .constraints = { poly_triple{ .a = schnorr_constraint.result, .b = schnorr_constraint.result, @@ -422,6 +430,8 @@ TEST_F(AcirFormatTests, TestVarKeccak) .ec_add_constraints = {}, .ec_double_constraints = {}, .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, .constraints = { dummy }, .block_constraints = {}, }; @@ -464,6 +474,8 @@ TEST_F(AcirFormatTests, TestKeccakPermutation) .ec_add_constraints = {}, .ec_double_constraints = {}, .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, .constraints = {}, .block_constraints = {} }; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp index 4e6b0f8a617..73d5aecf294 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp @@ -2,6 +2,7 @@ #include "acir_format.hpp" #include "barretenberg/common/container.hpp" #include "barretenberg/common/throw_or_abort.hpp" +#include "barretenberg/dsl/acir_format/bigint_constraint.hpp" #include "barretenberg/dsl/acir_format/blake2s_constraint.hpp" #include "barretenberg/dsl/acir_format/blake3_constraint.hpp" #include "barretenberg/dsl/acir_format/block_constraint.hpp" @@ -240,6 +241,40 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, aci .key_hash = arg.key_hash.witness.value, }; af.recursion_constraints.push_back(c); + } else if constexpr (std::is_same_v) { + af.bigint_from_le_bytes_constraints.push_back(BigIntFromLeBytes{ + .inputs = map(arg.inputs, [](auto& e) { return e.witness.value; }), + .modulus = map(arg.modulus, [](auto& e) -> uint32_t { return e; }), + .result = arg.output, + }); + } else if constexpr (std::is_same_v) { + af.bigint_operations.push_back(BigIntOperation{ + .lhs = arg.lhs, + .rhs = arg.rhs, + .result = arg.output, + .opcode = BigIntOperationType::Add, + }); + } else if constexpr (std::is_same_v) { + af.bigint_operations.push_back(BigIntOperation{ + .lhs = arg.lhs, + .rhs = arg.rhs, + .result = arg.output, + .opcode = BigIntOperationType::Neg, + }); + } else if constexpr (std::is_same_v) { + af.bigint_operations.push_back(BigIntOperation{ + .lhs = arg.lhs, + .rhs = arg.rhs, + .result = arg.output, + .opcode = BigIntOperationType::Mul, + }); + } else if constexpr (std::is_same_v) { + af.bigint_operations.push_back(BigIntOperation{ + .lhs = arg.lhs, + .rhs = arg.rhs, + .result = arg.output, + .opcode = BigIntOperationType::Div, + }); } }, arg.value.value); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp new file mode 100644 index 00000000000..4780e5ca36c --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.cpp @@ -0,0 +1,33 @@ +#include "bigint_constraint.hpp" +#include "barretenberg/dsl/types.hpp" +#include "barretenberg/numeric/uint256/uint256.hpp" +#include "barretenberg/stdlib/primitives/bigfield/bigfield.hpp" + +namespace acir_format { + +template void create_bigint_operations_constraint(Builder& builder, const BigIntOperation& input) +{ + // TODO + (void)builder; + info(input); +} + +template void create_bigint_operations_constraint(UltraCircuitBuilder& builder, + const BigIntOperation& input); +template void create_bigint_operations_constraint(GoblinUltraCircuitBuilder& builder, + const BigIntOperation& input); + +template +void create_bigint_from_le_bytes_constraint(Builder& builder, const BigIntFromLeBytes& input) +{ + // TODO + (void)builder; + info(input); +} + +template void create_bigint_from_le_bytes_constraint(UltraCircuitBuilder& builder, + const BigIntFromLeBytes& input); +template void create_bigint_from_le_bytes_constraint(GoblinUltraCircuitBuilder& builder, + const BigIntFromLeBytes& input); + +} // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp new file mode 100644 index 00000000000..8b21ee5e784 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.hpp @@ -0,0 +1,35 @@ +#pragma once +#include "barretenberg/dsl/types.hpp" +#include "barretenberg/serialize/msgpack.hpp" +#include +#include + +namespace acir_format { + +struct BigIntFromLeBytes { + std::vector inputs; + std::vector modulus; + uint32_t result; + + // For serialization, update with any new fields + MSGPACK_FIELDS(inputs, result); + friend bool operator==(BigIntFromLeBytes const& lhs, BigIntFromLeBytes const& rhs) = default; +}; + +enum BigIntOperationType { Add, Neg, Mul, Div }; + +struct BigIntOperation { + uint32_t lhs; + uint32_t rhs; + uint32_t result; + BigIntOperationType opcode; + + // For serialization, update with any new fields + MSGPACK_FIELDS(lhs, rhs, opcode, result); + friend bool operator==(BigIntOperation const& lhs, BigIntOperation const& rhs) = default; +}; + +template void create_bigint_operations_constraint(Builder& builder, const BigIntOperation& input); +template +void create_bigint_from_le_bytes_constraint(Builder& builder, const BigIntFromLeBytes& input); +} // namespace acir_format \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp new file mode 100644 index 00000000000..d53d1d8d731 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp @@ -0,0 +1,88 @@ +#include "bigint_constraint.hpp" +#include "acir_format.hpp" +#include "barretenberg/plonk/proof_system/types/proof.hpp" +#include "barretenberg/plonk/proof_system/verification_key/verification_key.hpp" + +#include +#include + +namespace acir_format::tests { + +class BigIntTests : public ::testing::Test { + protected: + static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } +}; + +TEST_F(BigIntTests, TestBigIntConstraintDummy) +{ + // Dummy Test: to be updated when big ints opcodes are implemented + BigIntOperation add_constraint{ + .lhs = 1, + .rhs = 2, + .result = 3, + .opcode = BigIntOperationType::Add, + }; + BigIntOperation neg_constraint{ + .lhs = 1, + .rhs = 2, + .result = 3, + .opcode = BigIntOperationType::Neg, + }; + BigIntOperation mul_constraint{ + .lhs = 1, + .rhs = 2, + .result = 3, + .opcode = BigIntOperationType::Mul, + }; + BigIntOperation div_constraint{ + .lhs = 1, + .rhs = 2, + .result = 3, + .opcode = BigIntOperationType::Div, + }; + BigIntFromLeBytes from_le_bytes_constraint{ + .inputs = { 0 }, + .modulus = { 23 }, + .result = 1, + }; + + acir_format constraint_system{ + .varnum = 4, + .public_inputs = {}, + .logic_constraints = {}, + .range_constraints = {}, + .sha256_constraints = {}, + .schnorr_constraints = {}, + .ecdsa_k1_constraints = {}, + .ecdsa_r1_constraints = {}, + .blake2s_constraints = {}, + .blake3_constraints = {}, + .keccak_constraints = {}, + .keccak_var_constraints = {}, + .keccak_permutations = {}, + .pedersen_constraints = {}, + .pedersen_hash_constraints = {}, + .fixed_base_scalar_mul_constraints = {}, + .ec_add_constraints = {}, + .ec_double_constraints = {}, + .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = { from_le_bytes_constraint }, + .bigint_operations = { add_constraint, neg_constraint, mul_constraint, div_constraint }, + .constraints = {}, + .block_constraints = {}, + + }; + + WitnessVector witness{ 0, 0, 1 }; + auto builder = create_circuit(constraint_system, /*size_hint*/ 0, witness); + + auto composer = Composer(); + auto prover = composer.create_ultra_with_keccak_prover(builder); + auto proof = prover.construct_proof(); + + auto verifier = composer.create_ultra_with_keccak_verifier(builder); + + EXPECT_EQ(verifier.verify_proof(proof), true); +} + +} // namespace acir_format::tests \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp index cb87035cae5..9c41912e13e 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp @@ -128,6 +128,8 @@ TEST_F(UltraPlonkRAM, TestBlockConstraint) .ec_add_constraints = {}, .ec_double_constraints = {}, .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, .constraints = {}, .block_constraints = { block }, }; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp index 841e71a148d..7a00666e74b 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp @@ -107,6 +107,8 @@ TEST_F(ECDSASecp256k1, TestECDSAConstraintSucceed) .ec_add_constraints = {}, .ec_double_constraints = {}, .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, .constraints = {}, .block_constraints = {}, }; @@ -151,6 +153,8 @@ TEST_F(ECDSASecp256k1, TestECDSACompilesForVerifier) .ec_add_constraints = {}, .ec_double_constraints = {}, .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, .constraints = {}, .block_constraints = {}, }; @@ -190,6 +194,8 @@ TEST_F(ECDSASecp256k1, TestECDSAConstraintFail) .ec_add_constraints = {}, .ec_double_constraints = {}, .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, .constraints = {}, .block_constraints = {}, }; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp index 72b5a616afc..e2ad73b7d4d 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp @@ -141,6 +141,8 @@ TEST(ECDSASecp256r1, test_hardcoded) .ec_add_constraints = {}, .ec_double_constraints = {}, .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, .constraints = {}, .block_constraints = {}, }; @@ -186,6 +188,8 @@ TEST(ECDSASecp256r1, TestECDSAConstraintSucceed) .ec_add_constraints = {}, .ec_double_constraints = {}, .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, .constraints = {}, .block_constraints = {}, }; @@ -229,6 +233,8 @@ TEST(ECDSASecp256r1, TestECDSACompilesForVerifier) .ec_add_constraints = {}, .ec_double_constraints = {}, .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, .constraints = {}, .block_constraints = {}, }; @@ -267,6 +273,8 @@ TEST(ECDSASecp256r1, TestECDSAConstraintFail) .ec_add_constraints = {}, .ec_double_constraints = {}, .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, .constraints = {}, .block_constraints = {}, }; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp index 457184ed025..25086e99c3f 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp @@ -100,6 +100,8 @@ Builder create_inner_circuit() .ec_add_constraints = {}, .ec_double_constraints = {}, .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, .constraints = { expr_a, expr_b, expr_c, expr_d }, .block_constraints = {} }; @@ -252,6 +254,8 @@ Builder create_outer_circuit(std::vector& inner_circuits) .ec_add_constraints = {}, .ec_double_constraints = {}, .recursion_constraints = recursion_constraints, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, .constraints = {}, .block_constraints = {} }; From 7727b3ea64a7a6dcde9c263e69464b7a1d93809f Mon Sep 17 00:00:00 2001 From: guipublic Date: Wed, 24 Jan 2024 11:08:14 +0000 Subject: [PATCH 5/9] using bigintegers opcodes in Noir --- noir/compiler/noirc_evaluator/src/errors.rs | 5 +- .../src/ssa/acir_gen/acir_ir.rs | 1 + .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 109 +++++++++++++++++- .../src/ssa/acir_gen/acir_ir/big_int.rs | 54 +++++++++ .../ssa/acir_gen/acir_ir/generated_acir.rs | 53 ++++----- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 29 ++++- noir/noir_stdlib/src/bigint.nr | 54 +++++++++ noir/noir_stdlib/src/lib.nr | 1 + 8 files changed, 268 insertions(+), 38 deletions(-) create mode 100644 noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs create mode 100644 noir/noir_stdlib/src/bigint.nr diff --git a/noir/compiler/noirc_evaluator/src/errors.rs b/noir/compiler/noirc_evaluator/src/errors.rs index d7229c0adc5..b7e89c7b213 100644 --- a/noir/compiler/noirc_evaluator/src/errors.rs +++ b/noir/compiler/noirc_evaluator/src/errors.rs @@ -44,6 +44,8 @@ pub enum RuntimeError { AssertConstantFailed { call_stack: CallStack }, #[error("Nested slices are not supported")] NestedSlice { call_stack: CallStack }, + #[error("Big Integer modulus do no match")] + BigIntModulus { call_stack: CallStack }, } // We avoid showing the actual lhs and rhs since most of the time they are just 0 @@ -132,7 +134,8 @@ impl RuntimeError { | RuntimeError::AssertConstantFailed { call_stack } | RuntimeError::IntegerOutOfBounds { call_stack, .. } | RuntimeError::UnsupportedIntegerSize { call_stack, .. } - | RuntimeError::NestedSlice { call_stack, .. } => call_stack, + | RuntimeError::NestedSlice { call_stack, .. } + | RuntimeError::BigIntModulus { call_stack, .. } => call_stack, } } } diff --git a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir.rs b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir.rs index 96800b22ad0..1ddbae0f339 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir.rs @@ -1,3 +1,4 @@ pub(crate) mod acir_variable; +pub(crate) mod big_int; pub(crate) mod generated_acir; pub(crate) mod sort; diff --git a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index cf7c6151110..5d4b0190c43 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1,3 +1,4 @@ +use super::big_int::BigIntContext; use super::generated_acir::GeneratedAcir; use crate::brillig::brillig_gen::brillig_directive; use crate::brillig::brillig_ir::artifact::GeneratedBrillig; @@ -107,6 +108,9 @@ pub(crate) struct AcirContext { /// then the `acir_ir` will be populated to assert this /// addition. acir_ir: GeneratedAcir, + + /// The BigIntContext, used to generate identifiers for BigIntegers + big_int_ctx: BigIntContext, } impl AcirContext { @@ -1140,10 +1144,10 @@ impl AcirContext { &mut self, name: BlackBoxFunc, mut inputs: Vec, - output_count: usize, + mut output_count: usize, ) -> Result, RuntimeError> { // Separate out any arguments that should be constants - let constants = match name { + let (constant_inputs, constant_outputs) = match name { BlackBoxFunc::PedersenCommitment | BlackBoxFunc::PedersenHash => { // The last argument of pedersen is the domain separator, which must be a constant let domain_var = match inputs.pop() { @@ -1167,23 +1171,116 @@ impl AcirContext { } }; - vec![domain_constant] + (vec![domain_constant], Vec::new()) + } + BlackBoxFunc::BigIntAdd + | BlackBoxFunc::BigIntNeg + | 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.vars[&var].as_constant() { + 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.as_field(), result_id.modulus_id()], + ) + } + BlackBoxFunc::BigIntToLeBytes => { + let const_inputs = vecmap(inputs, |i| { + let var = i.into_var()?; + match self.vars[&var].as_constant() { + 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 modulus = self.big_int_ctx.modulus(field_inputs[0]); + let bytes_nb = ((modulus - BigUint::from(1_u32)).bits() - 1) / 8 + 1; + output_count = bytes_nb as usize; + (field_inputs, vec![FieldElement::from(bytes_nb as u128)]) + } + 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.vars[&value.into_var()?].as_constant().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(FieldElement::from(modulus_id as u128)); + (modulus, vec![result_id.as_field(), result_id.modulus_id()]) } - _ => vec![], + _ => (vec![], vec![]), }; // Convert `AcirVar` to `FunctionInput` let inputs = self.prepare_inputs_for_black_box_func_call(inputs)?; // Call Black box with `FunctionInput` - let outputs = self.acir_ir.call_black_box(name, &inputs, constants, output_count)?; + let mut results = vecmap(&constant_outputs, |c| self.add_constant(*c)); + let outputs = self.acir_ir.call_black_box( + name, + &inputs, + constant_inputs, + constant_outputs, + output_count, + )?; // 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 - Ok(vecmap(&outputs, |witness_index| self.add_data(AcirVarData::Witness(*witness_index)))) + results.extend(vecmap(&outputs, |witness_index| { + self.add_data(AcirVarData::Witness(*witness_index)) + })); + Ok(results) } /// Black box function calls expect their inputs to be in a specific data structure (FunctionInput). diff --git a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs new file mode 100644 index 00000000000..06724180f8f --- /dev/null +++ b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs @@ -0,0 +1,54 @@ +use acvm::FieldElement; +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(crate) struct BigIntId(pub(crate) u32, pub(crate) u32); //bigint id, modulus id + +impl BigIntId { + pub(crate) fn as_field(&self) -> FieldElement { + FieldElement::from(self.0 as u128) + } + + pub(crate) fn modulus_id(&self) -> FieldElement { + FieldElement::from(self.1 as u128) + } +} + +/// BigIntContext is used to generate identifiers for big integers and their modulus +#[derive(Default, Debug)] +pub(crate) struct BigIntContext { + modulus: Vec, + big_integers: Vec, +} + +impl BigIntContext { + /// Creates a new BigIntId for the given modulus and returns it. + pub(crate) fn new_big_int(&mut self, modulus: FieldElement) -> BigIntId { + let id = self.big_integers.len() as u32; + let result = BigIntId(id, modulus.to_u128() as u32); + self.big_integers.push(result); + result + } + + /// Returns the modulus corresponding to the given modulus index + pub(crate) fn modulus(&self, idx: FieldElement) -> BigUint { + self.modulus[idx.to_u128() as usize].clone() + } + + /// Returns the BigIntId corresponding to the given identifier + pub(crate) fn get(&self, id: FieldElement) -> BigIntId { + self.big_integers[id.to_u128() as usize] + } + + /// Adds a modulus to the context (if it is not already present) + pub(crate) 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/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index 4572cf1dd08..5d9dce63bd0 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -138,7 +138,8 @@ impl GeneratedAcir { &mut self, func_name: BlackBoxFunc, inputs: &[Vec], - constants: Vec, + constant_inputs: Vec, + constant_outputs: Vec, output_count: usize, ) -> Result, InternalError> { let input_count = inputs.iter().fold(0usize, |sum, val| sum + val.len()); @@ -176,12 +177,12 @@ impl GeneratedAcir { BlackBoxFunc::PedersenCommitment => BlackBoxFuncCall::PedersenCommitment { inputs: inputs[0].clone(), outputs: (outputs[0], outputs[1]), - domain_separator: constants[0].to_u128() as u32, + domain_separator: constant_inputs[0].to_u128() as u32, }, BlackBoxFunc::PedersenHash => BlackBoxFuncCall::PedersenHash { inputs: inputs[0].clone(), output: outputs[0], - domain_separator: constants[0].to_u128() as u32, + domain_separator: constant_inputs[0].to_u128() as u32, }, BlackBoxFunc::EcdsaSecp256k1 => { BlackBoxFuncCall::EcdsaSecp256k1 { @@ -252,33 +253,34 @@ impl GeneratedAcir { key_hash: inputs[3][0], }, BlackBoxFunc::BigIntAdd => BlackBoxFuncCall::BigIntAdd { - lhs: constants[0].to_u128() as u32, - rhs: constants[1].to_u128() as u32, - output: constants[2].to_u128() as u32, + 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::BigIntNeg => BlackBoxFuncCall::BigIntNeg { - lhs: constants[0].to_u128() as u32, - rhs: constants[1].to_u128() as u32, - output: constants[2].to_u128() as u32, + 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: constants[0].to_u128() as u32, - rhs: constants[1].to_u128() as u32, - output: constants[2].to_u128() as u32, + 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: constants[0].to_u128() as u32, - rhs: constants[1].to_u128() as u32, - output: constants[2].to_u128() as u32, + 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(constants, |c| c.to_u128() as u8), - output: todo!(), + 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, }, - BlackBoxFunc::BigIntToLeBytes => { - BlackBoxFuncCall::BigIntToLeBytes { input: constants[0].to_u128() as u32, outputs } - } }; self.push_opcode(AcirOpcode::BlackBoxFuncCall(black_box_func_call)); @@ -636,16 +638,15 @@ fn black_box_func_expected_input_size(name: BlackBoxFunc) -> Option { // Doubling over the embedded curve: input is (x,y) coordinate of the point. BlackBoxFunc::EmbeddedCurveDouble => Some(2), - // Big integer operations take in 2 inputs + // Big integer operations take in 0 inputs. THey use constants for their inputs. BlackBoxFunc::BigIntAdd | BlackBoxFunc::BigIntNeg | BlackBoxFunc::BigIntMul - | BlackBoxFunc::BigIntDiv => Some(2), + | BlackBoxFunc::BigIntDiv + | BlackBoxFunc::BigIntToLeBytes => Some(0), // FromLeBytes takes a variable array of bytes as input BlackBoxFunc::BigIntFromLeBytes => None, - // ToLeBytes takes a single big integer as input - BlackBoxFunc::BigIntToLeBytes => Some(1), } } @@ -691,7 +692,7 @@ fn black_box_expected_output_size(name: BlackBoxFunc) -> Option { | BlackBoxFunc::BigIntNeg | BlackBoxFunc::BigIntMul | BlackBoxFunc::BigIntDiv - | BlackBoxFunc::BigIntFromLeBytes => Some(1), + | BlackBoxFunc::BigIntFromLeBytes => Some(0), // ToLeBytes returns a variable array of bytes BlackBoxFunc::BigIntToLeBytes => None, @@ -752,5 +753,5 @@ fn intrinsics_check_outputs(name: BlackBoxFunc, output_count: usize) { None => return, }; - assert_eq!(expected_num_outputs,output_count,"Tried to call black box function {name} with {output_count} inputs, but this function's definition requires {expected_num_outputs} inputs"); + assert_eq!(expected_num_outputs,output_count,"Tried to call black box function {name} with {output_count} outputs, but this function's definition requires {expected_num_outputs} outputs"); } diff --git a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index c0e3ed1ff66..b04fe0897e4 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -1710,7 +1710,7 @@ impl Context { let vars = self.acir_context.black_box_function(black_box, inputs, output_count)?; - Ok(Self::convert_vars_to_values(vars, dfg, result_ids)) + Ok(self.convert_vars_to_values(vars, dfg, result_ids)) } Intrinsic::ApplyRangeConstraint => { unreachable!("ICE: `Intrinsic::ApplyRangeConstraint` calls should be transformed into an `Instruction::RangeCheck`"); @@ -1757,7 +1757,7 @@ impl Context { .sort(input_vars, bit_size, self.current_side_effects_enabled_var) .expect("Could not sort"); - Ok(Self::convert_vars_to_values(out_vars, dfg, result_ids)) + Ok(self.convert_vars_to_values(out_vars, dfg, result_ids)) } Intrinsic::ArrayLen => { let len = match self.convert_value(arguments[0], dfg) { @@ -2392,16 +2392,35 @@ impl Context { /// Convert a Vec into a Vec using the given result ids. /// If the type of a result id is an array, several acir vars are collected into /// a single AcirValue::Array of the same length. + /// If the type of a result id is a slice, the slice length must precede it and we can + /// convert to an AcirValue::Array when the length is known (constant). fn convert_vars_to_values( + &self, vars: Vec, dfg: &DataFlowGraph, result_ids: &[ValueId], ) -> Vec { let mut vars = vars.into_iter(); - vecmap(result_ids, |result| { + let mut values: Vec = Vec::new(); + for result in result_ids { let result_type = dfg.type_of_value(*result); - Self::convert_var_type_to_values(&result_type, &mut vars) - }) + if let Type::Slice(elements_type) = result_type { + let error = "ICE - cannot get slice length when converting slice to AcirValue"; + let len = values.last().expect(error).borrow_var().expect(error); + let len = self.acir_context.constant(len).to_u128(); + let mut element_values = im::Vector::new(); + for _ in 0..len { + for element_type in elements_type.iter() { + let element = Self::convert_var_type_to_values(element_type, &mut vars); + element_values.push_back(element); + } + } + values.push(AcirValue::Array(element_values)); + } else { + values.push(Self::convert_var_type_to_values(&result_type, &mut vars)); + } + } + values } /// Recursive helper for convert_vars_to_values. diff --git a/noir/noir_stdlib/src/bigint.nr b/noir/noir_stdlib/src/bigint.nr new file mode 100644 index 00000000000..f3ecfba8343 --- /dev/null +++ b/noir/noir_stdlib/src/bigint.nr @@ -0,0 +1,54 @@ + +use crate::ops::{Add, Sub, Mul, Div, Rem,}; + +struct BigInt { + pointer: u32, + modulus: u32, +} + +impl BigInt { + #[builtin(bigint_add)] + pub fn bigint_add(self, other: BigInt) -> BigInt { + } + #[builtin(bigint_neg)] + pub fn bigint_neg(self, other: BigInt) -> BigInt { + } + #[builtin(bigint_mul)] + pub fn bigint_mul(self, other: BigInt) -> BigInt { + } + #[builtin(bigint_div)] + pub fn bigint_div(self, other: BigInt) -> BigInt { + } + #[builtin(bigint_from_le_bytes)] + pub fn from_le_bytes(bytes: [u8], modulus: [u8]) -> BigInt {} + #[builtin(bigint_to_le_bytes)] + pub fn to_le_bytes(self) -> [u8] {} +} + +impl Add for BigInt { + fn add(self: Self, other: BigInt) -> BigInt { + self.bigint_add(other) + } +} +impl Sub for BigInt { + fn sub(self: Self, other: BigInt) -> BigInt { + self.bigint_neg(other) + } +} +impl Mul for BigInt { + fn mul(self: Self, other: BigInt) -> BigInt { + self.bigint_mul(other) + } +} +impl Div for BigInt { + fn div(self: Self, other: BigInt) -> BigInt { + self.bigint_div(other) + } +} +impl Rem for BigInt { + fn rem(self: Self, other: BigInt) -> BigInt { + let quotient = self.bigint_div(other); + self.bigint_neg(quotient.bigint_mul(other)) + } +} + diff --git a/noir/noir_stdlib/src/lib.nr b/noir/noir_stdlib/src/lib.nr index 23a7c71ff45..c7e808c1029 100644 --- a/noir/noir_stdlib/src/lib.nr +++ b/noir/noir_stdlib/src/lib.nr @@ -24,6 +24,7 @@ mod ops; mod default; mod prelude; mod uint128; +mod bigint; // Oracle calls are required to be wrapped in an unconstrained function // Thus, the only argument to the `println` oracle is expected to always be an ident From d03b94d43cfa0040780a7668fd617dad25c04f08 Mon Sep 17 00:00:00 2001 From: guipublic Date: Wed, 24 Jan 2024 11:32:27 +0000 Subject: [PATCH 6/9] fix build issue --- .../dsl/acir_format/acir_format.test.cpp | 156 +++++++++--------- .../acir_format/recursion_constraint.test.cpp | 92 +++++------ 2 files changed, 124 insertions(+), 124 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp index 23c6da88249..8804cd0c573 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp @@ -141,29 +141,29 @@ TEST_F(AcirFormatTests, TestLogicGateFromNoirCircuit) // EXPR [ (1, _4, _6) (-1, _4) 0 ] // EXPR [ (-1, _6) 1 ] - acir_format constraint_system{ .varnum = 6, - .public_inputs = { 1 }, - .logic_constraints = { logic_constraint }, - .range_constraints = { range_a, range_b }, - .sha256_constraints = {}, - .schnorr_constraints = {}, - .ecdsa_k1_constraints = {}, - .ecdsa_r1_constraints = {}, - .blake2s_constraints = {}, - .blake3_constraints = {}, - .keccak_constraints = {}, - .keccak_var_constraints = {}, - .keccak_permutations = {}, - .pedersen_constraints = {}, - .pedersen_hash_constraints = {}, - .fixed_base_scalar_mul_constraints = {}, - .ec_add_constraints = {}, - .ec_double_constraints = {}, - .recursion_constraints = {}, - .bigint_from_le_bytes_constraints = {}, - .bigint_operations = {}, - .constraints = { expr_a, expr_b, expr_c, expr_d }, - .block_constraints = {} }; + AcirFormat constraint_system{ .varnum = 6, + .public_inputs = { 1 }, + .logic_constraints = { logic_constraint }, + .range_constraints = { range_a, range_b }, + .sha256_constraints = {}, + .schnorr_constraints = {}, + .ecdsa_k1_constraints = {}, + .ecdsa_r1_constraints = {}, + .blake2s_constraints = {}, + .blake3_constraints = {}, + .keccak_constraints = {}, + .keccak_var_constraints = {}, + .keccak_permutations = {}, + .pedersen_constraints = {}, + .pedersen_hash_constraints = {}, + .fixed_base_scalar_mul_constraints = {}, + .ec_add_constraints = {}, + .ec_double_constraints = {}, + .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, + .constraints = { expr_a, expr_b, expr_c, expr_d }, + .block_constraints = {} }; uint256_t inverse_of_five = fr(5).invert(); WitnessVector witness{ @@ -206,38 +206,38 @@ TEST_F(AcirFormatTests, TestSchnorrVerifyPass) .result = 76, .signature = signature, }; - acir_format constraint_system{ .varnum = 81, - .public_inputs = {}, - .logic_constraints = {}, - .range_constraints = range_constraints, - .sha256_constraints = {}, - .schnorr_constraints = { schnorr_constraint }, - .ecdsa_k1_constraints = {}, - .ecdsa_r1_constraints = {}, - .blake2s_constraints = {}, - .blake3_constraints = {}, - .keccak_constraints = {}, - .keccak_var_constraints = {}, - .keccak_permutations = {}, - .pedersen_constraints = {}, - .pedersen_hash_constraints = {}, - .fixed_base_scalar_mul_constraints = {}, - .ec_add_constraints = {}, - .ec_double_constraints = {}, - .recursion_constraints = {}, - .bigint_from_le_bytes_constraints = {}, - .bigint_operations = {}, - .constraints = { poly_triple{ - .a = schnorr_constraint.result, - .b = schnorr_constraint.result, - .c = schnorr_constraint.result, - .q_m = 0, - .q_l = 0, - .q_r = 0, - .q_o = 1, - .q_c = fr::neg_one(), - } }, - .block_constraints = {} }; + AcirFormat constraint_system{ .varnum = 81, + .public_inputs = {}, + .logic_constraints = {}, + .range_constraints = range_constraints, + .sha256_constraints = {}, + .schnorr_constraints = { schnorr_constraint }, + .ecdsa_k1_constraints = {}, + .ecdsa_r1_constraints = {}, + .blake2s_constraints = {}, + .blake3_constraints = {}, + .keccak_constraints = {}, + .keccak_var_constraints = {}, + .keccak_permutations = {}, + .pedersen_constraints = {}, + .pedersen_hash_constraints = {}, + .fixed_base_scalar_mul_constraints = {}, + .ec_add_constraints = {}, + .ec_double_constraints = {}, + .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, + .constraints = { poly_triple{ + .a = schnorr_constraint.result, + .b = schnorr_constraint.result, + .c = schnorr_constraint.result, + .q_m = 0, + .q_l = 0, + .q_r = 0, + .q_o = 1, + .q_c = fr::neg_one(), + } }, + .block_constraints = {} }; std::string message_string = "tenletters"; crypto::schnorr_key_pair account; @@ -455,29 +455,29 @@ TEST_F(AcirFormatTests, TestKeccakPermutation) 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50 }, }; - acir_format constraint_system{ .varnum = 51, - .public_inputs = {}, - .logic_constraints = {}, - .range_constraints = {}, - .sha256_constraints = {}, - .schnorr_constraints = {}, - .ecdsa_k1_constraints = {}, - .ecdsa_r1_constraints = {}, - .blake2s_constraints = {}, - .blake3_constraints = {}, - .keccak_constraints = {}, - .keccak_var_constraints = {}, - .keccak_permutations = { keccak_permutation }, - .pedersen_constraints = {}, - .pedersen_hash_constraints = {}, - .fixed_base_scalar_mul_constraints = {}, - .ec_add_constraints = {}, - .ec_double_constraints = {}, - .recursion_constraints = {}, - .bigint_from_le_bytes_constraints = {}, - .bigint_operations = {}, - .constraints = {}, - .block_constraints = {} }; + AcirFormat constraint_system{ .varnum = 51, + .public_inputs = {}, + .logic_constraints = {}, + .range_constraints = {}, + .sha256_constraints = {}, + .schnorr_constraints = {}, + .ecdsa_k1_constraints = {}, + .ecdsa_r1_constraints = {}, + .blake2s_constraints = {}, + .blake3_constraints = {}, + .keccak_constraints = {}, + .keccak_var_constraints = {}, + .keccak_permutations = { keccak_permutation }, + .pedersen_constraints = {}, + .pedersen_hash_constraints = {}, + .fixed_base_scalar_mul_constraints = {}, + .ec_add_constraints = {}, + .ec_double_constraints = {}, + .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, + .constraints = {}, + .block_constraints = {} }; WitnessVector witness{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp index 489769fe7b3..20650bf589b 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp @@ -81,29 +81,29 @@ Builder create_inner_circuit() .q_c = 1, }; - acir_format constraint_system{ .varnum = 6, - .public_inputs = { 1, 2 }, - .logic_constraints = { logic_constraint }, - .range_constraints = { range_a, range_b }, - .sha256_constraints = {}, - .schnorr_constraints = {}, - .ecdsa_k1_constraints = {}, - .ecdsa_r1_constraints = {}, - .blake2s_constraints = {}, - .blake3_constraints = {}, - .keccak_constraints = {}, - .keccak_var_constraints = {}, - .keccak_permutations = {}, - .pedersen_constraints = {}, - .pedersen_hash_constraints = {}, - .fixed_base_scalar_mul_constraints = {}, - .ec_add_constraints = {}, - .ec_double_constraints = {}, - .recursion_constraints = {}, - .bigint_from_le_bytes_constraints = {}, - .bigint_operations = {}, - .constraints = { expr_a, expr_b, expr_c, expr_d }, - .block_constraints = {} }; + AcirFormat constraint_system{ .varnum = 6, + .public_inputs = { 1, 2 }, + .logic_constraints = { logic_constraint }, + .range_constraints = { range_a, range_b }, + .sha256_constraints = {}, + .schnorr_constraints = {}, + .ecdsa_k1_constraints = {}, + .ecdsa_r1_constraints = {}, + .blake2s_constraints = {}, + .blake3_constraints = {}, + .keccak_constraints = {}, + .keccak_var_constraints = {}, + .keccak_permutations = {}, + .pedersen_constraints = {}, + .pedersen_hash_constraints = {}, + .fixed_base_scalar_mul_constraints = {}, + .ec_add_constraints = {}, + .ec_double_constraints = {}, + .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, + .constraints = { expr_a, expr_b, expr_c, expr_d }, + .block_constraints = {} }; uint256_t inverse_of_five = fr(5).invert(); WitnessVector witness{ @@ -235,29 +235,29 @@ Builder create_outer_circuit(std::vector& inner_circuits) circuit_idx++; } - acir_format constraint_system{ .varnum = static_cast(witness.size()), - .public_inputs = {}, - .logic_constraints = {}, - .range_constraints = {}, - .sha256_constraints = {}, - .schnorr_constraints = {}, - .ecdsa_k1_constraints = {}, - .ecdsa_r1_constraints = {}, - .blake2s_constraints = {}, - .blake3_constraints = {}, - .keccak_constraints = {}, - .keccak_var_constraints = {}, - .keccak_permutations = {}, - .pedersen_constraints = {}, - .pedersen_hash_constraints = {}, - .fixed_base_scalar_mul_constraints = {}, - .ec_add_constraints = {}, - .ec_double_constraints = {}, - .recursion_constraints = recursion_constraints, - .bigint_from_le_bytes_constraints = {}, - .bigint_operations = {}, - .constraints = {}, - .block_constraints = {} }; + AcirFormat constraint_system{ .varnum = static_cast(witness.size()), + .public_inputs = {}, + .logic_constraints = {}, + .range_constraints = {}, + .sha256_constraints = {}, + .schnorr_constraints = {}, + .ecdsa_k1_constraints = {}, + .ecdsa_r1_constraints = {}, + .blake2s_constraints = {}, + .blake3_constraints = {}, + .keccak_constraints = {}, + .keccak_var_constraints = {}, + .keccak_permutations = {}, + .pedersen_constraints = {}, + .pedersen_hash_constraints = {}, + .fixed_base_scalar_mul_constraints = {}, + .ec_add_constraints = {}, + .ec_double_constraints = {}, + .recursion_constraints = recursion_constraints, + .bigint_from_le_bytes_constraints = {}, + .bigint_operations = {}, + .constraints = {}, + .block_constraints = {} }; auto outer_circuit = create_circuit(constraint_system, /*size_hint*/ 0, witness); From 81babc13bf0b7fd183adad293f9615b707a139e5 Mon Sep 17 00:00:00 2001 From: guipublic Date: Wed, 24 Jan 2024 11:42:52 +0000 Subject: [PATCH 7/9] fix the build (2) --- .../src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp index d53d1d8d731..0762bfd783a 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp @@ -46,7 +46,7 @@ TEST_F(BigIntTests, TestBigIntConstraintDummy) .result = 1, }; - acir_format constraint_system{ + AcirFormat constraint_system{ .varnum = 4, .public_inputs = {}, .logic_constraints = {}, From 619b1e7d6961cd194182126f80df80ce98c75321 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Thu, 25 Jan 2024 10:36:06 +0000 Subject: [PATCH 8/9] Update noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs --- .../noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index 5d9dce63bd0..ac0981acfda 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -638,7 +638,7 @@ fn black_box_func_expected_input_size(name: BlackBoxFunc) -> Option { // Doubling over the embedded curve: input is (x,y) coordinate of the point. BlackBoxFunc::EmbeddedCurveDouble => Some(2), - // Big integer operations take in 0 inputs. THey use constants for their inputs. + // Big integer operations take in 0 inputs. They use constants for their inputs. BlackBoxFunc::BigIntAdd | BlackBoxFunc::BigIntNeg | BlackBoxFunc::BigIntMul From 5b48184b85254d94d50c99ec195bd66546e21338 Mon Sep 17 00:00:00 2001 From: guipublic Date: Thu, 25 Jan 2024 10:48:14 +0000 Subject: [PATCH 9/9] code review --- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 10 +++++----- .../src/ssa/acir_gen/acir_ir/big_int.rs | 17 ++++++++++------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 5d4b0190c43..d1c1e56f5a3 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1201,7 +1201,7 @@ impl AcirContext { let result_id = self.big_int_ctx.new_big_int(field_inputs[1]); ( vec![field_inputs[0], field_inputs[2]], - vec![result_id.as_field(), result_id.modulus_id()], + vec![result_id.bigint_id(), result_id.modulus_id()], ) } BlackBoxFunc::BigIntToLeBytes => { @@ -1221,9 +1221,9 @@ impl AcirContext { field_inputs.push(i?); } let modulus = self.big_int_ctx.modulus(field_inputs[0]); - let bytes_nb = ((modulus - BigUint::from(1_u32)).bits() - 1) / 8 + 1; - output_count = bytes_nb as usize; - (field_inputs, vec![FieldElement::from(bytes_nb as u128)]) + let bytes_len = ((modulus - BigUint::from(1_u32)).bits() - 1) / 8 + 1; + output_count = bytes_len as usize; + (field_inputs, vec![FieldElement::from(bytes_len as u128)]) } BlackBoxFunc::BigIntFromLeBytes => { let invalid_input = "ICE - bigint operation requires 2 inputs"; @@ -1254,7 +1254,7 @@ impl AcirContext { let modulus_id = self.big_int_ctx.get_or_insert_modulus(big_modulus); let result_id = self.big_int_ctx.new_big_int(FieldElement::from(modulus_id as u128)); - (modulus, vec![result_id.as_field(), result_id.modulus_id()]) + (modulus, vec![result_id.bigint_id(), result_id.modulus_id()]) } _ => (vec![], vec![]), }; diff --git a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs index 06724180f8f..c21188a8dbc 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs @@ -5,15 +5,18 @@ use num_bigint::BigUint; /// 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(crate) struct BigIntId(pub(crate) u32, pub(crate) u32); //bigint id, modulus id +pub(crate) struct BigIntId { + pub(crate) bigint_id: u32, + pub(crate) modulus_id: u32, +} impl BigIntId { - pub(crate) fn as_field(&self) -> FieldElement { - FieldElement::from(self.0 as u128) + pub(crate) fn bigint_id(&self) -> FieldElement { + FieldElement::from(self.bigint_id as u128) } pub(crate) fn modulus_id(&self) -> FieldElement { - FieldElement::from(self.1 as u128) + FieldElement::from(self.modulus_id as u128) } } @@ -25,10 +28,10 @@ pub(crate) struct BigIntContext { } impl BigIntContext { - /// Creates a new BigIntId for the given modulus and returns it. - pub(crate) fn new_big_int(&mut self, modulus: FieldElement) -> BigIntId { + /// Creates a new BigIntId for the given modulus identifier and returns it. + pub(crate) fn new_big_int(&mut self, modulus_id: FieldElement) -> BigIntId { let id = self.big_integers.len() as u32; - let result = BigIntId(id, modulus.to_u128() as u32); + let result = BigIntId { bigint_id: id, modulus_id: modulus_id.to_u128() as u32 }; self.big_integers.push(result); result }